@charset "UTF-8";

/* Foundations. Load brand.css and tokens.css before this file. */
* { box-sizing: border-box; }
html { font: 16px/var(--leading-body) var(--font-sans); color: var(--app-text); background: var(--app-ground); }
/* 업무 화면의 숫자는 모두 고정 폭이다. 본문 크기는 밀도 토큰(--app-body)을 따른다. */
body { margin: 0; font-size: var(--app-body); font-variant-numeric: tabular-nums; -webkit-font-smoothing: antialiased; word-break: keep-all; overflow-wrap: anywhere; }
a { color: inherit; text-decoration: none; }
:where(p, td, th, li) > a:not([class]) { color: var(--app-text); text-decoration: underline; text-underline-offset: 3px; }
button, input, select, textarea { font: inherit; }
button, a, input, textarea, select { -webkit-tap-highlight-color: transparent; }
button { cursor: pointer; }
button:disabled { opacity: .55; cursor: not-allowed; }
:where(a, button, input, textarea, select, summary):focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
h1, h2, h3, p { margin: 0; }
h1, h2, h3 { line-height: var(--leading-heading); letter-spacing: var(--tracking-heading); word-break: keep-all; overflow-wrap: anywhere; }
h1 { font-size: var(--app-title); font-weight: var(--weight-bold); }
h2 { font-size: var(--text-base); font-weight: var(--weight-semibold); }
/* 소제목은 본문보다 작아지지 않는다(직원 14px, 학생·학부모 15px). */
h3 { font-size: max(var(--text-md), var(--app-body)); font-weight: var(--weight-semibold); }
p { line-height: var(--leading-body); overflow-wrap: anywhere; }
small { display: block; font-size: var(--text-xs); color: var(--app-muted); }
code { font-size: var(--text-xs); background: var(--app-neutral-bg); border-radius: var(--app-radius-control); padding: 2px var(--space-1); overflow-wrap: anywhere; }
figure { margin: 0; }
fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
legend { padding: 0; font-size: var(--app-body); font-weight: var(--weight-semibold); color: var(--app-text); }
img { max-width: 100%; }
.icon { display: inline-block; vertical-align: middle; flex-shrink: 0; }
[hidden] { display: none !important; }

/* App shell: 틀과 종이. 옅은 회청 바탕(틀) 왼쪽에 사이드바를 두고, 작업 영역은 흰 종이 한 장(틀 안쪽 8px, 12px 모서리, 1px 테두리, 그림자 없음)이다. 위쪽 바는 두지 않는다. */
.sidebar { position: fixed; inset: 0 auto 0 0; width: var(--layout-sidebar); background: var(--app-ground); color: var(--app-text); padding: var(--space-4) var(--space-3) var(--space-3); display: flex; flex-direction: column; z-index: var(--z-navigation); }
.brand { display: inline-flex; align-items: center; gap: var(--space-3); font-size: var(--text-xl); letter-spacing: var(--tracking-heading); font-weight: var(--weight-heavy); flex-shrink: 0; }
.brand-mark { display: block; width: 52px; height: 52px; object-fit: contain; flex-shrink: 0; border-radius: var(--app-radius-panel); }
.brand small { font-size: .625rem; letter-spacing: var(--tracking-label); font-weight: var(--weight-medium); margin-top: var(--space-1); }
.sidebar .brand { gap: var(--space-2); padding-inline: var(--space-2); font-size: var(--text-base); line-height: var(--leading-tight); }
.sidebar .brand-mark { width: 32px; height: 32px; border-radius: var(--app-radius-control); }
.sidebar .brand small { color: var(--app-muted); margin-top: 2px; line-height: 0.75rem; }
/* 로고와 메뉴 한 줄의 높이를 정수 px로 둔다(rem 줄 높이). 소수 높이가 쌓이면 끝까지 스크롤해도 마지막 메뉴가 1px 못 되게 잘린다. */
.sidebar nav { display: grid; gap: 2px; margin-top: var(--space-4); overflow-y: auto; min-height: 0; scrollbar-width: thin; scroll-padding: var(--space-10); }
.sidebar nav.has-more { mask-image: linear-gradient(to bottom, currentColor calc(100% - var(--space-10)), transparent); }
.sidebar nav a { display: flex; align-items: center; gap: var(--space-2); min-height: var(--app-control-height); padding: var(--space-1) var(--space-2); border: 1px solid transparent; border-radius: var(--app-radius-control); color: var(--app-muted); font-size: var(--app-body); font-weight: var(--weight-medium); line-height: 1.25rem; transition: background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard); }
.sidebar nav a .icon { width: 18px; height: 18px; }
.sidebar nav a > span:first-of-type { text-wrap: balance; }
.sidebar nav a:hover { color: var(--app-text); background: var(--app-neutral-bg); }
/* 선택한 메뉴는 종이와 같은 흰 면에 네이비 글자와 1px 테두리. */
.sidebar nav a.active { color: var(--app-primary); background: var(--app-surface); border-color: var(--app-border); font-weight: var(--weight-semibold); }
/* 건수는 네이비 배지. */
/* relative: 숨은 구분 기호(.sr-only, absolute)가 휴대폰 가로 메뉴의 스크롤 밖으로 빠져 화면 폭을 넓히지 않게 한다. */
.nav-count { position: relative; margin-left: auto; padding: 0 0.375rem; border-radius: 4px; background: var(--app-primary); color: var(--app-inverse); font-size: 0.71875rem; font-weight: var(--weight-semibold); line-height: 1.25rem; white-space: nowrap; }
.nav-group { margin: var(--space-3) var(--space-2) var(--space-1); font-size: var(--text-xs); line-height: 1rem; color: var(--app-muted); }
.nav-rule { border: 0; border-top: 1px solid var(--app-border); margin: var(--space-2); }
.profile { margin-top: auto; border-top: 1px solid var(--app-border); padding-top: var(--space-3); display: flex; gap: var(--space-2); align-items: center; font-size: var(--text-sm); }
/* 이름을 누르면 내 계정으로 간다. */
.profile-link { display: flex; gap: var(--space-2); align-items: center; min-width: 0; min-height: var(--app-control-height); padding: var(--space-1); margin: calc(-1 * var(--space-1)); border-radius: var(--app-radius-control); color: inherit; text-decoration: none; }
.profile-link:hover { background: var(--app-neutral-bg); }
.profile-link[aria-current] { background: var(--app-surface); }
/* 이름·역할 두 줄과 로그아웃 버튼을 아바타(32px) 높이 안에 두어 프로필 높이가 정수로 떨어지게 한다(위의 메뉴 줄 높이와 같은 이유). */
.profile-link > span:last-child { min-width: 0; overflow-wrap: anywhere; line-height: var(--leading-tight); }
.profile form { margin-left: auto; }
.profile small, .profile .icon-button { color: var(--app-muted); }
.profile .icon-button { display: grid; place-items: center; }
.avatar { height: var(--space-8); width: var(--space-8); border-radius: var(--app-radius-round); background: var(--app-neutral-bg); color: var(--app-text); display: inline-grid; place-items: center; flex-shrink: 0; font-weight: var(--weight-semibold); }
.shell { margin-left: var(--layout-sidebar); padding: var(--space-2) var(--space-2) var(--space-2) 0; }
main { max-width: var(--layout-content); margin: auto; padding: var(--space-6) var(--space-10) var(--space-10); min-height: calc(100vh - 76px); }
/* 종이는 남은 폭을 다 쓰고, 내용은 --layout-content 안에서 가운데에 둔다(넓은 모니터에서 표가 한없이 늘어나지 않게). */
.shell main { max-width: none; margin: 0; min-height: calc(100vh - 2 * var(--space-2)); padding: var(--space-6) max(var(--space-8), calc((100% - var(--layout-content)) / 2)) var(--space-10); background: var(--app-surface); border: 1px solid var(--app-border); border-radius: var(--app-radius-sheet); }
/* 학생·학부모 휴대폰 아래 탭. 760px보다 넓으면 사이드바 메뉴를 쓰므로 숨긴다. */
.bottom-tabs { display: none; }
footer { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4); padding: var(--space-6) var(--space-10); border-top: 1px solid var(--app-border); font-size: var(--text-xs); color: var(--app-muted); }
footer b { letter-spacing: var(--tracking-label); color: var(--app-text); }
.public-shell footer { justify-content: center; }
.page-heading { display: flex; gap: var(--space-6); align-items: flex-end; justify-content: space-between; margin-bottom: var(--space-5); }
.page-heading > div { min-width: 0; }
.page-heading > .button { flex-shrink: 0; }
/* 제목 위 작은 라벨은 두지 않는다. 반 이름 같은 위치 정보는 제목 아래 부제 문장 앞에 붙인다. */
.page-heading p { color: var(--app-muted); font-size: var(--app-body); margin-top: var(--space-1); }
.dashboard-heading { padding-block: var(--space-2) var(--space-3); }

/* Controls */
.button { display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2); min-height: var(--app-control-height); border: 1px solid transparent; padding: var(--space-1) var(--space-3); border-radius: var(--app-radius-control); font-size: var(--app-body); font-weight: var(--weight-semibold); line-height: var(--leading-tight); text-align: center; transition: background-color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard); }
.button .icon { width: 16px; height: 16px; }
.primary { background: var(--app-primary); color: var(--app-inverse); }
.primary:hover:not(:disabled) { background: var(--app-primary-hover); }
.secondary { background: var(--app-surface); border-color: var(--app-control); color: var(--app-text); }
.secondary:hover:not(:disabled) { background: var(--app-ground); border-color: var(--app-field); }
/* 되돌리기 어려운 행동(삭제·해제·종료·숨기기). 네이비 주요 버튼과 구분되게 오류 적색 글자로 그린다. */
.secondary.danger { color: var(--app-bad); }
.secondary.danger:hover:not(:disabled) { background: var(--app-bad-bg); border-color: var(--app-bad); }
.secondary[aria-current], .secondary[aria-current]:hover:not(:disabled) { background: var(--app-primary); border-color: var(--app-primary); color: var(--app-inverse); }
.small { padding: var(--space-1) var(--space-2); font-size: var(--text-sm); }
.full { width: 100%; }
.full span { margin-left: auto; }
.icon-button { background: none; border: 0; border-radius: var(--app-radius-control); color: var(--app-muted); font-size: var(--text-lg); min-width: var(--app-control-height); min-height: var(--app-control-height); padding: var(--space-1); }
.icon-button:hover { background: var(--app-neutral-bg); color: var(--app-text); }
.text-button, .text-link { color: var(--app-text); font-size: var(--app-body); text-decoration: underline; text-underline-offset: 3px; }
.text-button { background: none; border: 0; min-height: var(--app-control-height); padding: var(--space-1) var(--space-2); }
.text-link { display: inline-flex; align-items: center; min-height: var(--app-control-height); }
label { display: block; font-size: var(--app-body); color: var(--app-text); font-weight: var(--weight-medium); min-width: 0; }
label input:not([type=checkbox]):not([type=radio]):not([type=file]), label select, label textarea { display: block; width: 100%; min-width: 0; margin-top: var(--space-1); padding: var(--space-1) var(--space-3); border: 1px solid var(--app-field); border-radius: var(--app-radius-control); background: var(--app-surface); color: var(--app-text); min-height: var(--app-input-height); font-size: var(--app-body); font-weight: var(--weight-regular); line-height: var(--leading-tight); }
input::placeholder, textarea::placeholder { color: var(--app-muted); opacity: 1; }
label small, .field-hint { margin-top: var(--space-1); font-weight: var(--weight-regular); }
input[type=checkbox], input[type=radio] { accent-color: var(--app-primary); width: 16px; height: 16px; flex-shrink: 0; }
input[aria-invalid=true], textarea[aria-invalid=true], select[aria-invalid=true] { border-color: var(--app-bad); }
input[type=file] { display: block; max-width: 100%; margin-top: var(--space-1); font-size: var(--text-sm); color: var(--app-muted); }
/* 파일 선택 버튼은 보조 버튼과 같은 모양이다. */
input[type=file]::file-selector-button { min-height: var(--app-control-height); margin-right: var(--space-3); padding: var(--space-1) var(--space-3); border: 1px solid var(--app-control); border-radius: var(--app-radius-control); background: var(--app-surface); color: var(--app-text); font: inherit; font-weight: var(--weight-semibold); cursor: pointer; }
input[type=file]:hover::file-selector-button { border-color: var(--app-field); background: var(--app-ground); }
/* 선택 상자 화살표는 메뉴 아이콘과 같은 선 아이콘으로 그린다. 선 색은 --app-muted. */
label select:not([multiple]) { appearance: none; padding-right: var(--space-8); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235d6673' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right var(--space-2) center; background-size: 16px; }
input[type=date], input[type=time], input[type=datetime-local] { font-variant-numeric: tabular-nums; }
::-webkit-calendar-picker-indicator { opacity: .55; cursor: pointer; }
::-webkit-calendar-picker-indicator:hover { opacity: 1; }
textarea, label textarea { resize: vertical; line-height: var(--leading-body); }
.check { display: flex; align-items: center; gap: var(--space-2); min-height: var(--app-control-height); }
.stack { display: grid; gap: var(--space-4); }
.stack > .button, .stack > .text-button { justify-self: start; }
.stack > .full { justify-self: stretch; }
.form-panel { max-width: var(--layout-form); margin-top: var(--space-6); }
.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4); }
.filter-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3); }
.filter-form > .form-grid { flex: 1 1 32rem; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: var(--space-3); }
#student-schedule .form-grid { grid-template-columns: repeat(auto-fit, minmax(min(9rem, 100%), 1fr)); }
.inline-form { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.inline-form:has(label) { align-items: end; }
/* 기록 탭: 옅은 회색 틀 안에서 현재 항목만 흰 면·네이비 글자·1px 테두리로 고른 상태를 보인다. */
.record-tabs { display: flex; flex-wrap: wrap; gap: 2px; width: fit-content; max-width: 100%; padding: 3px; margin-bottom: var(--space-5); background: var(--app-neutral-bg); border-radius: var(--app-radius-panel); }
.record-tabs .button { color: var(--app-muted); }
.record-tabs .button:hover { color: var(--app-text); background: var(--app-ground); }
.record-tabs .button[aria-current] { color: var(--app-primary); background: var(--app-surface); border-color: var(--app-border); }
.record-tabs .badge { align-self: center; }
/* 학생 기록 머리: 학생 목록으로 돌아가는 링크, 이름(h1)과 퇴원 표시, 학년·학교 | 수강 반 | 보호자 요약, 오른쪽에 메모 남기기.
   직원이 여는 모든 기록 탭 위에 같다(탭마다 따로 두던 "○○ 학생 ○○" 제목 대신). */
.record-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "back back" "title actions" "facts actions"; column-gap: var(--space-4); margin-bottom: var(--space-4); }
.back-link { grid-area: back; justify-self: start; display: inline-flex; align-items: center; gap: var(--space-1); min-height: var(--app-control-height); color: var(--app-muted); font-size: var(--text-sm); }
.back-link:hover { color: var(--app-text); text-decoration: underline; text-underline-offset: 3px; }
.record-title { grid-area: title; display: flex; align-items: center; gap: var(--space-2); min-width: 0; }
.record-facts { grid-area: facts; display: flex; flex-wrap: wrap; row-gap: var(--space-1); margin-top: var(--space-1); color: var(--app-muted); font-size: var(--app-body); }
.record-facts > span { padding-right: var(--space-3); }
.record-facts > span + span { padding-left: var(--space-3); border-left: 1px solid var(--app-border); }
.record-head > .heading-actions { grid-area: actions; align-self: end; }
/* 기록 탭 아래 한 줄: 그 탭의 안내(하위 화면이면 제목도), 오른쪽에 그 탭의 동작. */
.tab-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--space-2) var(--space-4); margin-bottom: var(--space-4); }
.tab-head > :first-child { min-width: 0; flex: 1 1 20rem; }
.tab-head h2 + .helper { margin-top: var(--space-1); }
/* 목록 도구 막대: 검색칸과 선택 상자를 한 줄에. 라벨은 화면 낭독기용이고, 선택 상자의 첫 항목(반 전체·학년 전체)이 이름을 대신한다. */
.toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-bottom: var(--space-3); }
.toolbar select { margin-top: 0; width: auto; min-width: 8rem; max-width: 14rem; }
.toolbar-search { position: relative; flex: 1 1 14rem; max-width: 22rem; }
.toolbar-search .icon { position: absolute; left: var(--space-2); top: 50%; width: 16px; height: 16px; transform: translateY(-50%); color: var(--app-muted); pointer-events: none; }
.toolbar label.toolbar-search input[type=search] { margin-top: 0; padding-left: var(--space-8); }
/* 필터 칩: 즉시 필터 양식 안의 건수 붙은 라디오 묶음. 기록 탭처럼 회색 틀 안에서 고른 칩만 흰 면·네이비 글자·1px 테두리다.
   라디오는 보이지 않게 두되 초점과 화살표 키는 그대로 받는다. 건수(.chip-count)는 id를 달아 결과와 함께 바꾼다. */
.filter-chips { display: inline-flex; flex-wrap: wrap; gap: 2px; min-width: 0; margin: 0; padding: 2px; border: 0; border-radius: var(--app-radius-panel); background: var(--app-neutral-bg); }
.filter-chips label { position: relative; display: inline-flex; font-weight: var(--weight-semibold); }
.filter-chips input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.filter-chips span { display: inline-flex; align-items: center; gap: var(--space-1); min-height: var(--app-control-height); padding: 0 var(--space-3); border: 1px solid transparent; border-radius: var(--app-radius-control); color: var(--app-muted); font-size: var(--text-sm); white-space: nowrap; }
.filter-chips label:hover span { color: var(--app-text); background: var(--app-ground); }
.filter-chips input:checked + span { color: var(--app-primary); background: var(--app-surface); border-color: var(--app-border); }
.filter-chips input:focus-visible + span { outline: 3px solid var(--focus); outline-offset: 1px; }
.chip-count { font-weight: var(--weight-regular); font-variant-numeric: tabular-nums; }
/* 처리할 일이 남은 칩의 건수(결석·보강의 처리할 것)는 대기 색 쌍의 작은 배지다. 오류가 남은 칩(카톡 알림의 실패)은 오류 색 쌍이다. */
.chip-count.due { padding: 0 var(--space-1); border-radius: 4px; background: var(--app-warn-bg); color: var(--app-warn); }
.chip-count.bad { padding: 0 var(--space-1); border-radius: 4px; background: var(--app-bad-bg); color: var(--app-bad); }
@media (max-width: 760px) {
  .filter-chips { display: flex; flex-basis: 100%; }
  .filter-chips label { flex: 1 1 auto; }
  .filter-chips span { justify-content: center; width: 100%; padding: 0 var(--space-2); }
}
/* 표만 담은 패널: 위에 건수 줄, 표는 패널 가장자리까지. */
.panel.table-panel { padding: 0; overflow: hidden; }
.table-meta { display: flex; align-items: center; justify-content: space-between; min-height: var(--app-control-height); padding: var(--space-1) var(--space-3); border-bottom: 1px solid var(--app-border); color: var(--app-muted); font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
/* 줄 전체를 누르는 표: 첫 칸의 링크(.row-link)가 줄 전체를 덮는다. 다른 칸에는 누를 것을 두지 않는다.
   iOS Safari(WebKit 버그 240961)는 tr의 position: relative를 무시해 덮개가 표 전체를 덮고 마지막 줄 링크가 모든 줄을 가린다.
   transform이 있으면 WebKit도 tr을 덮개의 기준 상자로 쓴다. */
.link-table tbody tr { position: relative; transform: translate(0); }
.link-table .row-link { color: var(--app-text); font-weight: var(--weight-semibold); }
.link-table .row-link::after { content: ''; position: absolute; inset: 0; }
.link-table tbody tr:hover .row-link { text-decoration: underline; text-underline-offset: 3px; }
.link-table td small { display: block; }
/* 보조 단의 작은 표: 줄 높이는 내용에 맞추고 첫 칸은 구획 왼쪽 선에 붙인다. */
.compact-table td { height: auto; padding: var(--space-2); }
.compact-table th { padding-inline: var(--space-2); }
.compact-table th:first-child, .compact-table td:first-child { padding-left: 0; }
.mono { color: var(--app-muted); font-variant-numeric: tabular-nums; }
/* 출결 관리 표: 반 색 칩(점 + 옅은 바탕 + 같은 계열 글자), 요약 한 줄, 상태에 맞는 동작 하나. */
.class-chip { --chip: var(--app-muted); --chip-bg: var(--app-neutral-bg); display: inline-flex; align-items: center; gap: var(--space-1); margin: 1px var(--space-1) 1px 0; padding: 0.0625rem var(--space-2) 0.0625rem 0.375rem; border-radius: 4px; background: var(--chip-bg); color: var(--chip); font-size: var(--text-sm); font-weight: var(--weight-semibold); white-space: nowrap; }
.class-chip::before { content: ''; width: 0.5rem; height: 0.5rem; border-radius: 50%; background: currentColor; flex-shrink: 0; }
.class-chip small { color: inherit; font-weight: var(--weight-regular); font-variant-numeric: tabular-nums; }
.cc-1 { --chip: var(--app-class-1); --chip-bg: var(--app-class-1-bg); }
.cc-2 { --chip: var(--app-class-2); --chip-bg: var(--app-class-2-bg); }
.cc-3 { --chip: var(--app-class-3); --chip-bg: var(--app-class-3-bg); }
.cc-4 { --chip: var(--app-class-4); --chip-bg: var(--app-class-4-bg); }
.cc-5 { --chip: var(--app-class-5); --chip-bg: var(--app-class-5-bg); }
.cc-6 { --chip: var(--app-class-6); --chip-bg: var(--app-class-6-bg); }
.cc-7 { --chip: var(--app-class-7); --chip-bg: var(--app-class-7-bg); }
.cc-8 { --chip: var(--app-class-8); --chip-bg: var(--app-class-8-bg); }
.cc-9 { --chip: var(--app-class-9); --chip-bg: var(--app-class-9-bg); }
.cc-10 { --chip: var(--app-class-10); --chip-bg: var(--app-class-10-bg); }
.cc-11 { --chip: var(--app-class-11); --chip-bg: var(--app-class-11-bg); }
.cc-12 { --chip: var(--app-class-12); --chip-bg: var(--app-class-12-bg); }
.board-table td.chips { white-space: normal; min-width: 12rem; width: 36%; }
.board-table .row-link { color: var(--app-text); font-weight: var(--weight-semibold); }
.board-table .row-action { text-align: right; white-space: nowrap; }
.board-summary { color: var(--app-muted); font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
.board-others > summary { cursor: pointer; font-weight: var(--weight-semibold); font-size: var(--app-body); }
/* 결석·보강: 접어 둔 등록 양식(학생 → 반 → 날짜 → 사유 한 줄), 표(결석일 · 학생 · 반 칩 · 사유 · 보강 일정 · 상태 · 동작),
   줄 아래로 펼치는 보강 양식(날짜 하나와 시작·종료 시각). */
.page-heading > .heading-actions { flex-shrink: 0; }
.register-panel { margin-bottom: var(--space-5); }
.register-grid { grid-template-columns: repeat(auto-fit, minmax(min(11rem, 100%), 1fr)); }
.field-note { color: var(--app-warn); font-size: var(--text-sm); font-weight: var(--weight-medium); }
.field-note:not(:empty) { margin-top: var(--space-1); }
.absence-table .a-student a { font-weight: var(--weight-semibold); }
.absence-table .a-student a:hover { text-decoration: underline; text-underline-offset: 3px; }
.absence-table .a-reason { min-width: 9rem; overflow-wrap: anywhere; }
.row-form { display: inline-block; }
.a-action > * + * { margin-left: var(--space-1); }
.makeup-row > td { height: auto; padding: var(--space-3); background: var(--app-ground); }
.makeup-panel { display: grid; gap: var(--space-2); }
.makeup-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3); }
.makeup-form label { flex: 0 1 10rem; }
.table-pages { display: flex; gap: var(--space-2); padding: var(--space-2) var(--space-3); border-top: 1px solid var(--app-border); }
/* 상담·후속 조치 표: 한 상담이 한 묶음(tbody)이다. 다음 조치(details)를 펼치면 아래 줄에 상담 메모·변경 이력·수정 양식이 열린다. */
.consult-table .c-due small { display: block; margin-top: 0; font-size: var(--text-xs); }
.consult-table .c-next { min-width: 14rem; }
.consult-table .row-link:hover { text-decoration: underline; text-underline-offset: 3px; }
.row-more > summary { display: list-item; align-content: center; font-weight: var(--weight-regular); overflow-wrap: anywhere; }
.row-more > summary::marker { color: var(--app-muted); }
.consult-table tr.consult-detail { display: none; }
.consult-item:has(details[open]) > tr.consult-detail { display: table-row; }
.consult-item:has(details[open]) > tr > td { background: var(--app-ground); }
/* 줄 사이 선은 상담 묶음 사이에만 둔다(펼친 줄과 그 상담 줄은 한 덩어리). */
.consult-item > tr > td { border-bottom: 0; }
.consult-item + .consult-item { border-top: 1px solid var(--app-rule); }
.consult-more { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); gap: var(--space-6); padding: var(--space-2) var(--space-1) var(--space-4); }
.consult-more h3 { margin: var(--space-4) 0 var(--space-1); font-size: var(--app-body); }
.consult-more h3:first-child { margin-top: 0; }
.consult-log { display: grid; gap: var(--space-1); margin: 0; padding: 0; list-style: none; color: var(--app-muted); font-size: var(--text-sm); }
.consult-log small { display: block; margin-top: 0; padding-left: var(--space-3); }
.consult-cancel { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2); margin-top: var(--space-4); padding-top: var(--space-3); border-top: 1px solid var(--app-border); }
.consult-cancel .helper { flex: 1 1 14rem; }
/* 학생·계정 관리: 계정마다 한 묶음(tbody) — 이름 · 아이디 · 역할 색 라벨 · 반 칩 · 보호자·자녀 · 상태 · 관리.
   '관리'(details)를 펼치면 상담 표처럼 아래 줄에 연결·비밀번호 재설정·계정 구획이 열린다. 도구 막대의 확인할 것 칩은 이름표를 붙인 둘째 묶음이다. */
.chip-group-label { color: var(--app-muted); font-size: var(--text-sm); font-weight: var(--weight-semibold); }
.people-table td.p-name, .people-table td.p-id { white-space: nowrap; }
.people-table .p-name a { font-weight: var(--weight-semibold); }
.people-table .p-name a:hover { text-decoration: underline; text-underline-offset: 3px; }
.people-table td.p-classes { min-width: 10rem; }
.people-table td.p-links { min-width: 8rem; }
.people-toggle > summary { list-style: none; }
.people-toggle > summary::-webkit-details-marker { display: none; }
.people-toggle[open] > summary { color: var(--app-primary); border-color: var(--app-primary); }
.people-table tr.people-detail { display: none; }
.people-item:has(details[open]) > tr.people-detail { display: table-row; }
.people-item:has(details[open]) > tr > td { background: var(--app-ground); }
.people-item > tr > td { border-bottom: 0; }
.people-item + .people-item { border-top: 1px solid var(--app-rule); }
.people-more { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-4) var(--space-6); padding: var(--space-2) var(--space-1) var(--space-4); }
.people-more h3 { margin-bottom: var(--space-2); font-size: var(--app-body); }
.people-more .stack { gap: var(--space-3); }
.people-more .helper + .text-link { display: inline-block; margin-top: var(--space-2); }
.people-links { display: grid; gap: var(--space-1); margin: 0 0 var(--space-2); padding: 0; list-style: none; }
.people-links small { display: inline; }
.people-links li { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-1) var(--space-2); min-height: var(--app-control-height); }
.people-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: var(--space-3) 0 var(--space-2); padding-top: var(--space-3); border-top: 1px solid var(--app-border); }
/* 휴대폰: 한 계정을 두 줄로 쌓는다(이름 | 역할 · 상태 | 관리, 그 아래 아이디 · 반 칩 · 보호자·자녀). 활성 표시와 빈 칸(—)은 걷는다. */
@media (max-width: 760px) {
  .people-table tbody.people-item { display: block; }
  .people-table tr.people-row { display: flex; flex-wrap: wrap; align-items: center; gap: 2px var(--space-2); padding: var(--space-2) var(--space-3); }
  .people-table tr.people-row::after { content: ''; order: 2; flex-basis: 100%; }
  .people-table tr.people-row > td { display: block; height: auto; padding: 0; border: 0; }
  .people-table td.p-name { order: 0; flex: 1 1 0; min-width: 0; white-space: normal; }
  .people-table td.p-role, .people-table td.p-status, .people-table td.p-action { order: 1; }
  .people-table td.p-id, .people-table td.p-classes, .people-table td.p-links { order: 3; min-width: 0; color: var(--app-muted); font-size: var(--text-xs); }
  .people-table td.p-status:has(> .muted), .people-table tr.people-row > td.none { display: none; }
  .people-item:has(details[open]) > tr.people-detail { display: block; }
  .people-table tr.people-detail > td { display: block; height: auto; padding: 0 var(--space-3); }
  .people-more { grid-template-columns: minmax(0, 1fr); }
}
/* 복습 과제 표: 과제마다 한 줄(반 칩 · 과제 · 수업일 · 마감 · 제출과 진행 막대 · 채점 대기 · 미제출 · 정답률 · 동작 하나). */
.assign-table .a-title { min-width: 14rem; }
.assign-table .a-title .badge { margin-left: var(--space-1); }
.assign-table .row-link:hover { text-decoration: underline; text-underline-offset: 3px; }
.assign-table .count { white-space: nowrap; }
/* 1340px 이하(1280·1366 노트북)에서는 수업일 열을 걷고 과제 이름을 두 줄까지 접어 아홉 칸이 종이 안에 들어오게 한다. */
@media (max-width: 1340px) {
  .assign-table .a-day { display: none; }
  .assign-table .a-title { min-width: 10rem; }
  .assign-table .progress { width: 3rem; }
}
.submit-cell { display: inline-flex; align-items: center; gap: var(--space-2); }
.submit-n { min-width: 3.5em; text-align: right; }
/* 진행 막대: 제출 수(글자) 앞의 보조 표시라 화면 낭독기에서는 숨긴다. 회색으로 차고, 모두 내면 완료 녹색이다. */
.progress { display: block; width: 4rem; height: 6px; border-radius: var(--app-radius-round); background: var(--app-border); overflow: hidden; }
.progress > span { display: block; height: 100%; background: var(--app-muted); }
.progress.done > span { background: var(--app-ok); }
.day-next:empty { display: none; }
.day-next { display: inline-flex; gap: var(--space-2); }
.toolbar label input[type=date][name] { margin-top: 0; width: auto; }
/* 종이책 숙제 진행 단계: 배부 → 학생 완료 → 학부모 확인 → 선생님 검사. 점을 세로선으로 잇는다.
   지난 단계는 녹색 점, 기다리는 단계는 황갈색 점, 아직인 단계는 회색 테두리 점이고, 상태는 언제나 옆 글자 배지로도 읽힌다. */
.homework-steps { list-style: none; margin: var(--space-2) 0 0; padding: 0; }
/* 단계 이름 | 상태·시각 두 칸. 첫 줄은 한 줄 높이를 채워 점과 가운데가 맞고, 검사 의견·여러 보호자 확인은 둘째 칸 아래로 쌓인다. */
.homework-steps .stage { position: relative; display: grid; grid-template-columns: 7rem minmax(0, 1fr); grid-template-rows: minmax(calc(var(--app-row) - 2 * var(--space-2)), auto); align-items: center; gap: var(--space-1) var(--space-4); padding-left: var(--space-6); border-bottom: 0; }
.homework-steps .stage > :not(b) { grid-column: 2; }
.homework-steps .stage::before { content: ''; position: absolute; left: 0; top: calc(var(--app-row) / 2 - 5px); width: 10px; height: 10px; box-sizing: border-box; border: 2px solid var(--app-field); border-radius: 50%; background: var(--app-surface); }
.homework-steps .stage.done::before { border-color: var(--app-ok); background: var(--app-ok); }
.homework-steps .stage.wait::before { border-color: var(--app-warn); background: var(--app-warn); }
.homework-steps .stage:not(:last-child)::after { content: ''; position: absolute; left: 4px; top: calc(var(--app-row) / 2 + 7px); bottom: calc(7px - var(--app-row) / 2); width: 2px; background: var(--app-rule); }
/* 공지사항: 직원 공지 관리표(상태 · 제목 · 대상 칩 · 받는 사람 · 공개 · 확인 n/m과 진행 막대 · 작성 · 이동),
   공지 화면(왼쪽 본문과 받는 사람별 확인 표, 오른쪽 확인 현황), 받는 범위를 반 색 칩으로 고르는 작성 양식. */
.announce-table .an-title { min-width: 14rem; }
.announce-table .row-link:hover { text-decoration: underline; text-underline-offset: 3px; }
.announce-table .an-target .class-chip { white-space: normal; }
.announce-table .an-reach { white-space: nowrap; }
.announce-layout { display: grid; grid-template-columns: minmax(0, 1fr) var(--layout-aside); grid-template-areas: "body side" "reads side"; grid-template-rows: auto 1fr; gap: var(--space-6) var(--space-8); align-items: start; }
.announce-body { grid-area: body; }
.announce-side { grid-area: side; display: grid; gap: var(--space-2); min-width: 0; }
.announce-reads { grid-area: reads; min-width: 0; }
.announce-reads > .section-heading { flex-wrap: wrap; }
.announce-reads .toolbar { margin: 0; }
.announce-edit { margin-top: var(--space-4); padding-top: var(--space-3); border-top: 1px solid var(--app-border); }
.announce-edit > summary { cursor: pointer; font-weight: var(--weight-semibold); }
.reach-total { font-variant-numeric: tabular-nums; }
.reach-total b { font-size: var(--text-lg); }
.progress.wide { width: 100%; }
.reach-table .count { width: 4.5rem; white-space: nowrap; }
.reach-table th[scope=row] .class-chip { white-space: normal; }
.reads-table th small { display: block; color: var(--app-muted); font-size: var(--text-xs); font-weight: var(--weight-regular); }
.reads-table td.chips { width: 40%; }
.announce-form { max-width: var(--layout-form); }
.announce-form > .form-actions { border-top: 1px solid var(--app-border); padding-top: var(--space-4); }
.student-options.target-picker { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(15rem, 100%), 1fr)); gap: var(--space-1) var(--space-4); }
.target-picker .class-chip { margin: 0; white-space: normal; }
.target-picker small { font-variant-numeric: tabular-nums; white-space: nowrap; }
.target-picker > .helper { grid-column: 1 / -1; }
.announce-feed .learn-row small .class-chip { margin-right: var(--space-2); }
/* 1150px 이하에서는 확인 현황을 본문 아래로 내리고, 공지 표의 받는 사람·작성 열을 걷는다. */
@media (max-width: 1150px) {
  .announce-layout { grid-template-columns: minmax(0, 1fr); grid-template-areas: "body" "side" "reads"; grid-template-rows: none; }
  .announce-side { max-width: var(--layout-form); }
  .announce-table .an-audience, .announce-table .an-author { display: none; }
}
/* 휴대폰: 공지 표는 한 공지를 두 줄로 쌓는다(제목 | 상태, 그 아래 대상 칩 · 공개 · 확인). 받는 사람별 확인 표도
   이름 | 확인, 그 아래 구분 · 반 칩으로 쌓는다. 머리글은 .board-table 규칙으로 화면 낭독기에만 남는다. */
@media (max-width: 760px) {
  .announce-table tbody, .reads-table tbody { display: block; }
  .announce-table tr, .reads-table tr { display: flex; flex-wrap: wrap; align-items: center; gap: 2px var(--space-2); padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--app-rule); }
  .announce-table tr:last-child, .reads-table tr:last-child { border-bottom: 0; }
  .announce-table tr::after, .reads-table tr::after { content: ''; order: 2; flex-basis: 100%; }
  .announce-table tr > *, .reads-table tr > * { display: block; height: auto; padding: 0; border: 0; }
  .announce-table td.an-title, .reads-table th[scope=row] { order: 0; flex: 1 1 0; min-width: 0; }
  .announce-table td.an-status, .reads-table td.r-status { order: 1; }
  .announce-table td.an-target, .announce-table td.an-date, .announce-table td.an-reach, .reads-table td.r-role, .reads-table td.chips { order: 3; color: var(--app-muted); font-size: var(--text-xs); }
  .announce-table td.an-date::before { content: '공개 '; }
  .announce-table td.an-reach::before { content: '확인 '; }
  .announce-table td.an-reach:has(.muted)::before { content: none; }
  .announce-table td.an-date:has(.muted) { display: none; }
  .announce-table .row-action, .announce-table .an-audience, .announce-table .an-author, .announce-table .progress { display: none; }
  .reads-table td.chips { width: auto; min-width: 0; }
  /* 확인 현황의 반별 표는 세 칸이라 일반 표의 32rem 최소 폭을 덮어 가로 스크롤 없이 둔다. */
  .announce-side .table-wrap > table.compact-table.reach-table { min-width: 0; }
}
/* 학부모 알림장: 대상 월 표(월 · 학생 · 반 칩 · 제목 · 상태 · 공개 · 학부모 확인 · 동작), 그달 알림장이 없는 학생 목록,
   상세의 본문 | 진행 단계 두 단, 학부모 목록의 자녀별 묶음. */
.note-meta { flex-wrap: wrap; gap: 0 var(--space-4); }
.note-meta .meta-links { display: inline-flex; flex-wrap: wrap; gap: var(--space-3); white-space: nowrap; }
.note-table .n-student, .note-table .n-class { white-space: nowrap; }
.note-table .n-title { min-width: 14rem; overflow-wrap: anywhere; }
.note-table .row-link:hover { text-decoration: underline; text-underline-offset: 3px; }
.note-missing > h2 .count { color: var(--app-muted); font-size: var(--app-body); font-weight: var(--weight-regular); font-variant-numeric: tabular-nums; }
.note-missing ul { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(24rem, 100%), 1fr)); column-gap: var(--space-8); margin: var(--space-2) 0 0; padding: 0; list-style: none; }
.note-missing li { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-1) var(--space-3); min-height: var(--app-row); padding: var(--space-1) 0; border-bottom: 1px solid var(--app-rule); }
.note-missing li .class-chip { margin: 0 0 0 var(--space-1); }
.missing-actions { display: inline-flex; gap: var(--space-3); }
.note-layout { display: grid; grid-template-columns: minmax(0, 1fr) var(--layout-aside); grid-template-areas: "body side" "edit side"; gap: var(--space-4) var(--space-8); align-items: start; }
.note-layout > .note-body { grid-area: body; }
.note-layout > .note-side { grid-area: side; }
.note-layout > .note-edit { grid-area: edit; margin-top: 0; }
.note-body .prose { max-width: 46rem; }
.note-side > h2 { margin-bottom: var(--space-1); }
.note-compose { max-width: var(--layout-form); }
.note-class label { max-width: 20rem; }
#note-student > .helper { margin-top: var(--space-2); }
.note-child + .note-child { margin-top: var(--space-6); padding-top: var(--space-4); border-top: 1px solid var(--app-border); }
.note-child > h2 { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-bottom: var(--space-1); }
@media (max-width: 960px) {
  .note-layout { grid-template-columns: minmax(0, 1fr); grid-template-areas: "body" "side" "edit"; }
}
@media (max-width: 760px) {
  /* 한 알림장을 쌓는다: (월) / 학생 | 상태, 제목, 반 칩 | 학부모 확인, 동작. 공개 시각과 빈 확인 칸은 숨긴다. */
  .note-table tr.note-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--space-1) var(--space-2); padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--app-rule); }
  .note-table tr.note-row > td { height: auto; padding: 0; border: 0; }
  .note-table td.n-month { grid-column: 1 / -1; color: var(--app-muted); font-size: var(--text-sm); }
  .note-table td.n-student { order: 1; font-weight: var(--weight-semibold); }
  .note-table td.n-status { order: 2; text-align: right; }
  .note-table td.n-title { order: 3; grid-column: 1 / -1; min-width: 0; }
  .note-table td.n-class { order: 4; }
  .note-table td.n-read { order: 5; text-align: right; }
  .note-table td.n-read.none, .note-table td.row-action:empty { display: none; }
  .note-table td.row-action { order: 6; grid-column: 1 / -1; text-align: left; }
}
/* 상담 신청 접수함: 신청마다 한 줄(접수 · 학생과 학년 · 신청한 사람 · 가린 연락처 · 관심 반 칩 · 자주 틀리는 이유 · 상태 · 동작 하나),
   아래에 월별 신청 작은 표와 알림 메일. 상세는 학생 기록 머리 모양의 머리와 두 단(왼쪽 신청 내용·처리, 오른쪽 처리 이력). */
.inquiry-table .i-student { min-width: 7rem; }
.inquiry-table .row-link:hover { text-decoration: underline; text-underline-offset: 3px; }
.inquiry-table .i-grade { color: var(--app-muted); font-size: var(--text-sm); white-space: nowrap; }
.inquiry-table .i-phone { font-variant-numeric: tabular-nums; }
.inquiry-table .i-class { min-width: 9.5rem; }
.inquiry-table .i-class .class-chip { white-space: normal; }
.inquiry-table .i-reasons { min-width: 8rem; }
/* 자주 틀리는 이유: 상태가 아닌 분류라 중립 바탕의 작은 글자 표(배지보다 가볍게, 굵기 없이). */
.reason-tag { display: inline-block; margin: 1px var(--space-1) 1px 0; padding: 0 var(--space-1); border-radius: 4px; background: var(--app-neutral-bg); color: var(--app-muted); font-size: var(--text-xs); line-height: 1.5; white-space: nowrap; }
.inquiry-foot { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: var(--space-6) var(--space-8); align-items: start; margin-top: var(--space-6); padding-top: var(--space-5); border-top: 1px solid var(--app-border); }
.inquiry-foot > section:only-child { grid-column: 1 / -1; max-width: var(--layout-form); }
.inquiry-months .count { width: 4.5rem; white-space: nowrap; }
.inquiry-months th[scope=row] { white-space: nowrap; }
.inquiry-layout { display: grid; grid-template-columns: minmax(0, 1fr) var(--layout-aside); gap: var(--space-6) var(--space-8); align-items: start; }
.inquiry-main, .inquiry-side { min-width: 0; }
/* 처리 이력: 위에서부터 접수 → 상태를 바꾼 기록. 점을 세로선으로 잇는다(상태는 글자로 읽힌다). */
.inquiry-history { list-style: none; margin: var(--space-3) 0 var(--space-3); padding: 0; }
.inquiry-history li { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0 var(--space-2); padding: 0 0 var(--space-3) var(--space-5); }
.inquiry-history li::before { content: ''; position: absolute; left: 0; top: 0.45em; width: 9px; height: 9px; box-sizing: border-box; border: 2px solid var(--app-muted); border-radius: 50%; background: var(--app-surface); }
.inquiry-history li:last-child::before { background: var(--app-muted); }
.inquiry-history li:not(:last-child)::after { content: ''; position: absolute; left: 4px; top: calc(0.45em + 11px); bottom: 2px; width: 1px; background: var(--app-border); }
.inquiry-history b { font-weight: var(--weight-semibold); }
.inquiry-history small { grid-column: 1 / -1; color: var(--app-muted); font-size: var(--text-xs); }
/* 1340px 이하(1280·1366 노트북)에서는 신청한 사람 열을, 1150px 이하에서는 가린 연락처 열도 걷어 표가 종이 안에 들어오게 한다
   (둘 다 상세 화면에 있고, 연락처 숫자로 찾기는 그대로다). */
@media (max-width: 1340px) {
  .inquiry-table .i-applicant { display: none; }
}
@media (max-width: 1150px) {
  .inquiry-table .i-phone { display: none; }
  .inquiry-foot, .inquiry-layout { grid-template-columns: minmax(0, 1fr); }
  .inquiry-side { max-width: var(--layout-form); }
}
/* 휴대폰: 한 신청을 학생·학년 | 상태 | 동작, 그 아래 접수 · 연락처, 관심 반 칩·이유로 쌓는다. 빈 칸(—)은 숨긴다. */
@media (max-width: 760px) {
  .inquiry-table tbody { display: block; }
  .inquiry-table tr { display: flex; flex-wrap: wrap; align-items: center; gap: 2px var(--space-2); padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--app-rule); }
  .inquiry-table tr:last-child { border-bottom: 0; }
  .inquiry-table tr::after { content: ''; order: 2; flex-basis: 100%; }
  .inquiry-table tr > * { display: block; height: auto; padding: 0; border: 0; }
  .inquiry-table td.i-student { order: 0; flex: 1 1 0; min-width: 0; }
  .inquiry-table td.i-status, .inquiry-table td.row-action { order: 1; }
  .inquiry-table td.row-action:empty { display: none; }
  .inquiry-table td.i-date, .inquiry-table td.i-phone, .inquiry-table td.i-class, .inquiry-table td.i-reasons { order: 3; min-width: 0; color: var(--app-muted); font-size: var(--text-xs); }
  .inquiry-table td.i-date::before { content: '접수 '; }
  .inquiry-table td.i-phone { display: block; }
  .inquiry-table td.none, .inquiry-table td.i-applicant { display: none; }
  /* 월별 신청은 연락함·종결 열을 걷어 다섯 칸으로 줄이고, 일반 표의 32rem 최소 폭을 덮어 가로 스크롤 없이 둔다. */
  .inquiry-foot .table-wrap > table.compact-table.inquiry-months { min-width: 0; }
  .inquiry-months .m-contacted, .inquiry-months .m-closed { display: none; }
  .inquiry-months .count { width: auto; }
}
.nowrap { white-space: nowrap; }
.narrow-only { display: none; }
.grow { flex: 1; min-width: 0; }
.form-actions { display: flex; justify-content: space-between; align-items: center; gap: var(--space-4); padding: var(--space-2) 0; }
.form-actions > .button { flex-shrink: 0; }
/* 복습 과제 만들기: 긴 양식이라 입력란이 넓은 종이 끝까지 늘어나지 않게 폭을 둔다. 단계는 상자 없이 윗줄로 나눈다. */
.assignment-form { max-width: 60rem; }
.assignment-form > .form-actions { border-top: 1px solid var(--app-border); padding-top: var(--space-4); }
.student-options { border: 1px solid var(--app-border); border-radius: var(--app-radius-panel); padding: var(--space-3) var(--space-4); display: flex; gap: var(--space-4); flex-wrap: wrap; min-width: 0; }
.student-options legend { font-size: var(--app-body); padding: 0 var(--space-2); }
.recipient-picker { margin-top: var(--space-5); }
.recipient-tools { display: flex; gap: var(--space-4); width: 100%; }
.recipient-group { display: flex; gap: var(--space-4); flex-wrap: wrap; width: 100%; }
.recipient-group[hidden] { display: none; }

/* Layout and data */
.amber-text { color: var(--app-warn) !important; }
/* 패널은 8px 모서리와 1px 테두리, 그림자 없이. */
.panel { background: var(--app-surface); border: 1px solid var(--app-border); border-radius: var(--app-radius-panel); padding: var(--space-4); min-width: 0; }
.panel > h2 { margin-bottom: var(--space-3); }
/* 화면의 주인공 카드만 .panel 상자로 두고, 보조 구획은 상자 없이 제목과 윗줄로 나눈다. */
.plain { padding: var(--space-4) 0 0; border-top: 1px solid var(--app-border); min-width: 0; }
.plain > h2 { margin-bottom: var(--space-3); }
.section-heading { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-3); }
.section-heading:has(> .heading-actions) { flex-wrap: wrap; }
.side-stack { display: grid; gap: var(--space-6); align-content: start; min-width: 0; }
/* 상태 배지: 4px 모서리, 상태색 쌍(글자/바탕), 언제나 한국어 글자와 함께. 색 이름 없는 배지는 중립. */
.badge { display: inline-block; border-radius: 4px; padding: 0.125rem 0.375rem; font-size: 0.71875rem; font-weight: var(--weight-semibold); line-height: 1.4; white-space: nowrap; font-variant-numeric: tabular-nums; background: var(--app-neutral-bg); color: var(--app-muted); }
.badge + .badge { margin-left: var(--space-1); }
/* Existing semantic class names remain compatible with all role templates. */
.green { background: var(--app-ok-bg); color: var(--app-ok); }
.amber { background: var(--app-warn-bg); color: var(--app-warn); }
.red { background: var(--app-bad-bg); color: var(--app-bad); }
.neutral { background: var(--app-neutral-bg); color: var(--app-muted); }
/* 표: 머리글은 12px 회색, 한 줄은 --app-row(40px), 줄 사이는 옅은 선. 개수 열(.count)은 오른쪽 정렬. */
.table-wrap { position: relative; overflow: auto; max-width: 100%; }
table { border-collapse: collapse; width: 100%; font-size: var(--app-body); text-align: left; }
th { color: var(--app-muted); font-size: var(--text-xs); font-weight: var(--weight-semibold); padding: var(--space-2) var(--space-3); white-space: nowrap; border-bottom: 1px solid var(--app-border); }
th[scope=row] { height: var(--app-row); color: var(--app-text); font-size: var(--app-body); white-space: normal; padding: var(--space-1) var(--space-3); border-bottom-color: var(--app-rule); }
td { height: var(--app-row); padding: var(--space-1) var(--space-3); border-bottom: 1px solid var(--app-rule); vertical-align: middle; overflow-wrap: break-word; font-variant-numeric: tabular-nums; }
@media (hover: hover) { tbody tr:hover > td, tbody tr:hover > th { background: var(--app-ground); } }
tr:last-child td, tr:last-child th[scope=row] { border-bottom: 0; }
tbody tr:hover { background: var(--app-ground); }
.row-title { font-size: var(--app-body); font-weight: var(--weight-semibold); display: block; min-width: 150px; max-width: 265px; }
.row-title:hover { text-decoration: underline; text-underline-offset: 4px; }
td small { margin-top: var(--space-1); }
td .button, td .text-link { white-space: nowrap; }
.arrow-link { border: 1px solid var(--app-border); border-radius: var(--app-radius-round); width: var(--app-control-height); height: var(--app-control-height); display: grid; place-items: center; color: var(--app-text); }
.arrow-link:hover { background: var(--app-neutral-bg); }
.class-mini { display: flex; align-items: center; gap: var(--space-3); border-top: 1px solid var(--app-border); padding: var(--space-4) 0; }
.class-mini:last-child { padding-bottom: 0; }
.class-mini > span:nth-child(2) { flex: 1; min-width: 0; }
.class-mini b { font-size: var(--text-sm); display: block; }
.class-icon { min-width: var(--space-10); min-height: var(--space-10); padding: var(--space-1); border-radius: var(--app-radius-control); background: var(--app-neutral-bg); color: var(--app-text); display: grid; place-items: center; font-size: var(--text-xs); flex-shrink: 0; }
/* 오늘의 현황: 제목 줄에 날짜, 그 아래 먼저 볼 한 줄(본문 글자색). */
.title-line { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--space-2); }
.title-line > span { color: var(--app-muted); font-size: var(--text-md); font-variant-numeric: tabular-nums; }
.dashboard-heading .finding { color: var(--app-text); font-weight: var(--weight-medium); margin-top: var(--space-2); }
.dashboard-heading > .heading-actions { flex-shrink: 0; }
.heading-links { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 0 var(--space-4); color: var(--app-muted); font-variant-numeric: tabular-nums; }
/* 오늘 수업 띠: 선생님 이름 열 + 정시 눈금. 블록은 반 색(.cc-N의 옅은 면과 같은 계열 글자, 반 이름과 함께), 지금 수업은 네이비 면에 흰 글자, 지금 시각은 2px 적색 선.
   한 시간에 4.5rem 이상을 주고, 그보다 좁으면 띠 안에서만 가로로 스크롤한다(선생님 이름은 왼쪽에 붙어 있다).
   한 선생님의 수업이 겹치면 그 줄만 수업 줄 높이(--strip-row-height)를 겹친 수만큼 쌓는다(.stacked, --strip-rows, 블록마다 --strip-row). */
.time-strip { --strip-name: 4rem; --strip-row-height: 4.5rem; border: 1px solid var(--app-border); border-radius: var(--app-radius-panel); padding: var(--space-3) var(--space-4) var(--space-4); margin-bottom: var(--space-5); min-width: 0; }
.time-strip > .section-heading { margin-bottom: var(--space-1); }
.strip-scroll { overflow-x: auto; }
.strip-scroll:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.strip-body { --strip-hours: 1; position: relative; min-width: calc(var(--strip-name) + var(--strip-hours) * 4.5rem); }
.strip-hours { display: grid; grid-template-columns: repeat(var(--strip-hours), minmax(0, 1fr)); align-items: end; height: var(--space-6); margin-left: var(--strip-name); padding-bottom: var(--space-1); color: var(--app-muted); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
.strip-hours > span { padding-left: var(--space-1); }
.strip-lane { display: grid; grid-template-columns: var(--strip-name) minmax(0, 1fr); border-top: 1px solid var(--app-rule); }
.strip-teacher { position: sticky; left: 0; z-index: 2; display: flex; align-items: center; padding-right: var(--space-2); background: var(--app-surface); font-size: var(--text-sm); font-weight: var(--weight-semibold); word-break: keep-all; }
.strip-track { --strip-rows: 1; position: relative; min-height: calc(var(--strip-rows) * var(--strip-row-height)); border-right: 1px solid var(--app-rule); background: linear-gradient(to right, var(--app-rule) 1px, transparent 1px) 0 0 / calc(100% / var(--strip-hours)) 100%; }
/* 블록은 지금 시각 선 위에 놓아(z-index) 선이 반 이름·등원 수를 가로지르지 않는다. 선은 빈 칸과 시각 줄에서 보인다. */
.strip-block { --strip-row: 0; position: absolute; z-index: 1; top: var(--space-1); bottom: var(--space-1); display: flex; flex-direction: column; justify-content: center; padding: var(--space-1) var(--space-2); overflow: hidden; border: 1px solid var(--app-surface); border-radius: var(--app-radius-control); background: var(--chip-bg, var(--app-neutral-bg)) padding-box; color: var(--chip, var(--app-muted)); font-size: var(--text-xs); line-height: 1.35; font-variant-numeric: tabular-nums; }
.strip-block > * { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.strip-block b { font-size: var(--text-sm); font-weight: var(--weight-semibold); }
a.strip-block:hover b { text-decoration: underline; text-underline-offset: 3px; }
.strip-block[aria-current] { background-color: var(--app-primary); color: var(--app-inverse); }
.strip-track.stacked > .strip-block { top: calc(var(--strip-row) * var(--strip-row-height) + var(--space-1)); bottom: auto; height: calc(var(--strip-row-height) - 2 * var(--space-1)); }
.strip-now-layer { position: absolute; top: 0; bottom: 0; left: var(--strip-name); right: 0; z-index: 0; pointer-events: none; }
.strip-now { position: absolute; top: 0; bottom: 0; width: 2px; margin-left: -1px; background: var(--app-bad); }
.strip-now > span { position: absolute; top: 0; left: var(--space-1); padding: 0 var(--space-1); border-radius: 4px; background: var(--app-bad); color: var(--app-inverse); font-size: 0.71875rem; font-weight: var(--weight-semibold); line-height: 1.5; font-variant-numeric: tabular-nums; white-space: nowrap; }
.strip-now[data-end] > span { left: auto; right: var(--space-1); }
.strip-note, .strip-empty { margin-top: var(--space-2); font-size: var(--text-sm); color: var(--app-muted); }
.strip-empty { color: var(--app-text); }
/* 처리할 일 표(주인공 상자)와 원장의 새 상담 신청. 넓은 화면에서 두 칸, 1150px 이하에서 한 칸. */
.dashboard-main { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-4); align-items: start; }
.dashboard-main.has-aside { grid-template-columns: minmax(0, 1fr) 14.5rem; }
.todo-table td:nth-child(2) { font-weight: var(--weight-semibold); }
.todo-table td:nth-child(3), .todo-table td.due { color: var(--app-muted); }
.todo-table td:last-child { text-align: right; }
.todo-empty { padding: var(--space-1) 0 var(--space-3); color: var(--app-muted); }
.inquiry-line { display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--space-2); padding: var(--space-1) 0 var(--space-2); border-top: 1px solid var(--app-rule); }
.inquiry-line small { flex-basis: 100%; color: var(--app-muted); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
/* 처리할 일 아래 접은 최근 제출 완료. 처리할 일 표·건수와 섞지 않는다. */
.todo-done { margin-top: var(--space-3); border-top: 1px solid var(--app-rule); padding-top: var(--space-1); }
.todo-done > summary { display: list-item; align-content: center; font-size: var(--app-body); }
.todo-done > ul { margin: 0; padding: 0; list-style: none; }
.todo-done li { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-3); min-height: var(--app-row); padding: var(--space-1) 0; border-top: 1px solid var(--app-rule); }
.todo-done li > .text-link { font-weight: var(--weight-semibold); }
.todo-done li > small { color: var(--app-muted); font-variant-numeric: tabular-nums; }
/* 앞으로 7일: 날짜마다 한 줄. 수업·보강은 시각 순으로 왼쪽부터 놓고 넘치면 다음 줄로 잇는다(시각 → 반 색 칩). */
.week-ahead { margin-top: var(--space-6); }
.week-table th[scope=row] { width: 8.5rem; white-space: nowrap; font-weight: var(--weight-semibold); }
.week-table th[scope=row], .week-table td { vertical-align: top; padding-block: var(--space-2); }
.week-table .count { width: 6rem; }
.week-items { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); margin: 0; padding: 0; list-style: none; }
.week-items > li { display: inline-flex; align-items: center; gap: var(--space-1); white-space: nowrap; }
.week-items time { min-width: 2.75rem; color: var(--app-muted); font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
.week-items .class-chip { margin: 0; }
.week-note { color: var(--app-muted); font-size: var(--text-sm); }
/* 수업 시간표 주간 격자(tt-): 시각 열 + 월~일 열, 한 시간에 --tt-hour. 블록은 반 색(.cc-N의 옅은 면과 같은 계열 글자, 반 이름과 함께)이고
   위치(--tt-top·--tt-height: 축에 대한 %)와 겹칠 때 나란히 놓을 칸(--tt-col/--tt-cols)은 서버가 정한다. 오늘 열은 틀 색 면과 '오늘' 글자,
   지금 시각은 오늘 열의 2px 적색 선(오늘의 현황 띠와 같은 색). 760px 이하에서는 같은 마크업이 요일별 목록이 된다. */
.schedule-board { --tt-hour: 2.75rem; --tt-head: 2.25rem; }
.tt-views { display: inline-flex; flex-wrap: wrap; gap: var(--space-1); }
.tt-scroll { overflow-x: auto; }
.tt-scroll:focus-visible { outline: 3px solid var(--focus); outline-offset: -3px; }
.tt-grid { --tt-hours: 1; display: grid; grid-template-columns: 3rem repeat(7, minmax(7rem, 1fr)); padding: 0 var(--space-3) var(--space-3) 0; }
.tt-axis { position: relative; margin-top: var(--tt-head); height: calc(var(--tt-hours) * var(--tt-hour)); color: var(--app-muted); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
.tt-axis > span { --tt-top: 0%; position: absolute; top: var(--tt-top); right: var(--space-2); transform: translateY(-50%); line-height: 1; }
.tt-day { min-width: 0; border-left: 1px solid var(--app-rule); }
.tt-day:last-child { border-right: 1px solid var(--app-rule); }
.tt-day[aria-current] { background: var(--app-ground); }
.tt-head { display: flex; align-items: center; gap: var(--space-1); height: var(--tt-head); padding: 0 var(--space-2); border-bottom: 1px solid var(--app-border); font-size: var(--text-sm); white-space: nowrap; }
.tt-head small { margin-left: auto; color: var(--app-muted); font-size: var(--text-xs); font-weight: var(--weight-regular); font-variant-numeric: tabular-nums; }
.tt-today { padding: 0 var(--space-1); border: 1px solid var(--app-border); border-radius: 4px; background: var(--app-surface); font-size: var(--text-xs); }
.tt-body { position: relative; height: calc(var(--tt-hours) * var(--tt-hour)); background: linear-gradient(to bottom, var(--app-rule) 1px, transparent 1px) 0 0 / 100% var(--tt-hour); }
.tt-block { --tt-top: 0%; --tt-height: 0%; --tt-col: 0; --tt-cols: 1; position: absolute; z-index: 1; top: var(--tt-top); left: calc(var(--tt-col) * 100% / var(--tt-cols)); width: calc(100% / var(--tt-cols)); height: var(--tt-height); display: flex; flex-flow: column wrap; align-content: flex-start; column-gap: var(--space-2); padding: 0.125rem var(--space-1) 0.125rem 0.375rem; overflow: hidden; border: 1px solid var(--app-surface); border-radius: var(--app-radius-control); background: var(--chip-bg, var(--app-neutral-bg)) padding-box; color: var(--chip, var(--app-muted)); font-size: var(--text-xs); line-height: 1.35; font-variant-numeric: tabular-nums; }
.tt-block > * { flex-shrink: 0; width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 반 이름은 좁은 칸에서 두 줄까지 접고, 남는 높이에 시각·담당·학생 수를 둔다. 높이에 다 들어가지 않는 줄은 반쯤 잘려 보이지 않게
   옆 단(칸 밖)으로 넘겨 통째로 감춘다(column wrap). 잘린 글자는 title로 다 읽힌다. */
.tt-block b { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; white-space: normal; word-break: keep-all; overflow-wrap: anywhere; font-size: var(--text-sm); font-weight: var(--weight-semibold); }
a.tt-block:hover b { text-decoration: underline; text-underline-offset: 3px; }
.tt-now { --tt-top: 0%; position: absolute; z-index: 2; left: 0; right: 0; top: var(--tt-top); height: 2px; margin-top: -1px; background: var(--app-bad); pointer-events: none; }
.tt-now::before { content: ''; position: absolute; left: -5px; top: -4px; width: 10px; height: 10px; border-radius: 50%; background: var(--app-bad); }
.tt-none { display: none; }
.tt-empty, .tt-note { padding: var(--space-3); color: var(--app-muted); font-size: var(--text-sm); }
/* 선생님별 보기는 격자가 선생님 수만큼 이어지므로 한 시간을 조금 낮게 둔다. */
.tt-teacher { --tt-hour: 2.25rem; }
.tt-teacher + .tt-teacher, .tt-teacher + .tt-note { border-top: 1px solid var(--app-border); }
.tt-teacher-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--space-2); padding: var(--space-3) var(--space-3) var(--space-2); }
.tt-teacher-head > span { color: var(--app-muted); font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
/* 학생별 표: 요일 칸마다 시각 → 반 색 칩(클리닉은 회색). 좁은 화면에서도 요일 열이 읽히게 표 안에서만 가로로 스크롤한다. */
.tt-students { min-width: 56rem; }
.tt-students th[scope=col]:nth-child(n+2) { width: 12.5%; }
.tt-students td { vertical-align: top; padding-block: var(--space-2); }
.tt-students td > small { margin-top: var(--space-1); color: var(--app-muted); font-size: var(--text-xs); }
.tt-students .today { background: var(--app-ground); }
.tt-slots { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
.tt-slots li { display: grid; justify-items: start; gap: 0.125rem; }
.tt-slots small { color: var(--app-muted); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
.tt-slots .class-chip { margin: 0; white-space: normal; }
.tt-makeups { margin: 0; padding: 0; list-style: none; }
.tt-makeups li { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-3); min-height: var(--app-row); padding: var(--space-1) 0; border-top: 1px solid var(--app-rule); font-variant-numeric: tabular-nums; }
.tt-makeups .class-chip { margin: 0; }
@media (max-width: 760px) {
  .tt-grid { display: block; padding: 0 var(--space-3); }
  .tt-axis, .tt-now { display: none; }
  .tt-day, .tt-day:last-child { border: 0; padding: var(--space-2) 0 var(--space-3); }
  .tt-day + .tt-day { border-top: 1px solid var(--app-rule); }
  .tt-day[aria-current] { margin: 0 calc(-1 * var(--space-3)); padding-inline: var(--space-3); }
  .tt-head { height: auto; padding: 0 0 var(--space-2); border: 0; }
  .tt-head small { margin-left: var(--space-1); }
  .tt-body { position: static; height: auto; display: grid; gap: var(--space-1); background: none; }
  .tt-block { position: static; width: auto; height: auto; flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 0 var(--space-2); min-height: var(--app-control-height); padding: var(--space-2); }
  .tt-block > *, .tt-block b { display: inline; width: auto; white-space: normal; }
  .tt-block .tt-time { order: -1; }
  .tt-none { display: block; color: var(--app-muted); font-size: var(--text-sm); }
}
.slot-teachers { width: 100%; }
.two-col { display: grid; grid-template-columns: minmax(0, 1fr) var(--layout-aside); gap: var(--space-4); align-items: start; }
.spaced { margin-top: var(--space-4); }
.page-action { margin-bottom: var(--space-6); }
.card-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-4); }
/* 반과 진도: 제목 줄 오른쪽 '새 반 만들기'는 <details>의 summary다. 제목 줄에 겹쳐 두고, 펼친 양식은 제목 아래로 내용을 밀어 낸다. */
.heading-with-create { position: relative; }
.heading-with-create > .page-heading { min-height: var(--app-control-height); align-items: center; padding-right: 10rem; }
.heading-create > summary { position: absolute; top: 0; right: 0; list-style: none; }
.heading-create > summary::-webkit-details-marker { display: none; }
.create-panel { max-width: var(--layout-form); margin-bottom: var(--space-5); }
.class-table .class-chip { white-space: normal; }
.class-table td > .badge { margin-left: var(--space-1); }
/* 반 화면: 학생 기록 머리 모양의 반 머리(제목은 반 색 칩), 왼쪽 학생·진도 표와 오른쪽 수업 시간·설정 두 단. */
.class-head h1 .class-chip { margin: 0; padding: 0 var(--space-2); gap: var(--space-2); border-radius: var(--app-radius-control); font-size: inherit; font-weight: inherit; white-space: normal; }
.class-note { margin: calc(-1 * var(--space-2)) 0 var(--space-4); }
.class-layout { display: grid; grid-template-columns: minmax(0, 1fr) 24rem; gap: var(--space-8); align-items: start; }
.class-main, .class-side { display: grid; gap: var(--space-6); align-content: start; min-width: 0; }
.class-main .section-heading { flex-wrap: wrap; }
.class-side > .plain:first-child { padding-top: 0; border-top: 0; }
.class-students .row-action, .former-students .row-action { width: 1%; text-align: right; white-space: nowrap; }
.table-foot { display: grid; gap: var(--space-1); padding: var(--space-3); border-top: 1px solid var(--app-border); }
.former-students > summary { display: list-item; align-content: center; font-size: var(--app-body); }
.slot-row { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2) 0; border-bottom: 1px solid var(--app-rule); }
.slot-row > span { flex: 1; min-width: 0; }
.slot-row b, .slot-row small { display: block; }
.slot-row small { color: var(--app-muted); font-variant-numeric: tabular-nums; }
.slot-form { margin-top: var(--space-4); gap: var(--space-3); }
.slot-fields { display: grid; grid-template-columns: 5rem minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-2); }
/* 오른쪽 단(24rem)을 두면 1150px 이하에서 학생·진도 표가 너무 좁아지므로 한 단으로 쌓는다. */
@media (max-width: 1150px) {
  .class-layout { grid-template-columns: minmax(0, 1fr); }
  .class-side > .plain:first-child { padding-top: var(--space-4); border-top: 1px solid var(--app-border); }
}
/* 반 표와 반 화면의 표는 열이 적어 휴대폰에서도 가로 스크롤 없이 접는다(일반 표의 32rem 최소 폭을 덮는다).
   반 표는 담당·과정을 반 이름 아래 한 줄로 옮긴다. */
@media (max-width: 760px) {
  #class-results .table-wrap > table, .class-layout .class-main .table-wrap > table:is(.class-students, .progress-table, .compact-table) { min-width: 0; }
  .class-meta.narrow-only { display: block; margin-top: 2px; color: var(--app-muted); font-size: var(--text-xs); }
}
/* 일일·월간 테스트: 종류 색 라벨(배지 모양, 점 없음), 진행·비율 막대, 테스트 화면의 결과 요약과 문항별 O/X 줄. */
.kind-daily { background: var(--app-kind-daily-bg); color: var(--app-kind-daily); }
.kind-monthly { background: var(--app-kind-monthly-bg); color: var(--app-kind-monthly); }
.role-student { background: var(--app-role-student-bg); color: var(--app-role-student); }
.role-parent { background: var(--app-role-parent-bg); color: var(--app-role-parent); }
.role-teacher { background: var(--app-role-teacher-bg); color: var(--app-role-teacher); }
.role-admin { background: var(--app-role-admin-bg); color: var(--app-role-admin); }
.meter { display: inline-block; width: 4rem; height: 0.375rem; border-radius: var(--app-radius-round); background: var(--app-neutral-bg); overflow: hidden; vertical-align: middle; }
.meter > span { display: block; height: 100%; border-radius: inherit; background: var(--app-muted); }
.meter.full > span, .rate-list .meter > span { background: var(--app-ok); }
.test-table td small { color: var(--app-muted); font-size: var(--text-xs); }
.test-table .badge + .class-chip { margin-left: var(--space-1); }
.test-grid th[scope=col] .badge { margin-left: 2px; }
.test-grid th small { display: block; font-weight: var(--weight-regular); }
.test-head .record-title .badge { align-self: center; }
.test-form { max-width: var(--layout-form); }
.void-form { max-width: var(--layout-form); }
/* 테스트 화면: 왼쪽 학생별 결과, 오른쪽 결과 요약(320px). 1150px 이하에서 한 단으로 쌓는다. */
.test-layout { display: grid; grid-template-columns: minmax(0, 1fr) var(--layout-aside); gap: var(--space-8); align-items: start; margin-top: var(--space-5); padding-top: var(--space-4); border-top: 1px solid var(--app-border); }
.test-main > .section-heading, .test-summary > h2 { margin-bottom: var(--space-3); }
.entry-table input:not([type=checkbox]) { margin-top: 0; width: 14rem; max-width: 100%; }
.entry-table input[type=number] { width: 6rem; }
.entry-table td small, .student-test-table td small, .trend-table td small { display: inline; margin: 0 0 0 var(--space-1); }
.test-summary h3 { margin: var(--space-5) 0 var(--space-2); font-size: var(--app-body); }
/* 요약 수는 상자(타일) 없이 키-값 줄로 둔다. */
.summary-facts { margin: 0; }
.summary-facts > div { display: flex; justify-content: space-between; gap: var(--space-3); padding: var(--space-1) 0; border-bottom: 1px solid var(--app-rule); }
.summary-facts dt { color: var(--app-muted); }
.summary-facts dd { margin: 0; font-weight: var(--weight-semibold); font-variant-numeric: tabular-nums; }
.bar-list { display: grid; gap: var(--space-1); margin: 0; padding: 0; list-style: none; font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
.bar-list li { display: grid; grid-template-columns: 4.5rem minmax(0, 1fr) 3.25rem; align-items: center; gap: var(--space-2); }
.rate-list li { grid-template-columns: 2.5rem minmax(0, 1fr) 3.25rem; }
.bar-list .meter { width: 100%; height: 0.5rem; }
.bar-list .count { text-align: right; }
.test-summary > .helper { margin-top: var(--space-2); }
.ox-strip { display: grid; grid-template-columns: repeat(10, 1.375rem); gap: 2px; }
.ox { display: grid; place-items: center; height: 1.375rem; border-radius: 4px; font-size: 0.6875rem; font-weight: var(--weight-semibold); font-variant-numeric: tabular-nums; }
.ox-o { background: var(--app-ok-bg); color: var(--app-ok); }
.ox-x { background: var(--app-bad); color: var(--app-inverse); }
.ox-wait { background: var(--app-warn-bg); color: var(--app-warn); outline: 1px dashed var(--app-warn); outline-offset: -1px; }
.trend-table th[scope=row] { white-space: nowrap; font-weight: var(--weight-semibold); }
.entry-table th[scope=row] { word-break: keep-all; }
#grade-sheet > .section-heading { flex-wrap: wrap; }
/* 학생 탭의 달마다 표는 열 폭을 고정해 달이 바뀌어도 열이 같은 자리에 온다. */
.student-test-table { table-layout: fixed; }
.student-test-table th:nth-child(1) { width: 9rem; }
.student-test-table th:nth-child(2) { width: 28%; }
.student-test-table th:nth-child(3) { width: 5rem; }
.student-test-table th:nth-child(5) { width: 13rem; }
.student-test-table .class-chip { white-space: normal; }
@media (max-width: 1150px) {
  .test-layout { grid-template-columns: minmax(0, 1fr); }
  .test-summary { max-width: var(--layout-form); }
}
/* 휴대폰: 테스트 목록은 날짜·반·종류를 제목 아래 한 줄로 옮겨 가로 스크롤 없이 접는다.
   테스트 화면의 입력 표는 문항별 O/X 열을 숨기고 입력칸을 줄여 결과·결시까지 한 화면에 둔다. */
@media (max-width: 760px) {
  #test-results .table-wrap > table, .test-layout .test-main .table-wrap > table.entry-table { min-width: 0; }
  .entry-table input:not([type=checkbox]), .entry-table input[type=number] { width: 100%; min-width: 4.5rem; }
  .test-meta.narrow-only { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1); margin-top: 2px; color: var(--app-muted); font-size: var(--text-xs); }
  .test-meta .class-chip { margin: 0; }
  .test-table .meter { display: none; }
}
/* 월간 학습 리포트: 반 × 학생 표(학생 · 제출 막대 · 정답률 · 숙제 막대 · 등원 · 결석 · 테스트 평균 · 리포트 상태 · 동작)와
   학생 한 명의 리포트(왼쪽 초안에 들어가는 집계와 참고, 오른쪽 초안 만들기). 막대는 복습 과제 표의 진행 막대(.progress)다. */
.report-table td { white-space: nowrap; }
.report-table .row-link { color: var(--app-text); font-weight: var(--weight-semibold); }
.report-table .row-link:hover { text-decoration: underline; text-underline-offset: 3px; }
.report-table .row-action { text-align: right; }
.report-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-8); align-items: start; margin-top: var(--space-5); padding-top: var(--space-4); border-top: 1px solid var(--app-border); }
.report-stats .report-metrics { display: block; margin: var(--space-2) 0 var(--space-3); }
.report-stats .report-metrics > div { display: grid; grid-template-columns: 10.5rem minmax(0, 1fr); align-items: center; gap: var(--space-3); min-height: var(--app-row); padding: var(--space-1) 0; border-bottom: 1px solid var(--app-rule); }
.report-stats .report-metrics dt { color: var(--app-muted); }
.report-stats .report-metrics dd { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); font-variant-numeric: tabular-nums; }
.report-stats .report-metrics dd .muted { font-weight: var(--weight-regular); }
.report-reference { margin-top: var(--space-6); }
.report-reference h3 { margin-bottom: var(--space-2); font-size: var(--app-body); }
.report-reference .helper { margin-top: var(--space-2); }
/* 1340px 이하(노트북)에서는 참고 열인 테스트 평균을 걷어 열 칸이 종이 안에 들어오게 한다(학생 리포트 화면에 있다). */
@media (max-width: 1340px) {
  .report-table .r-test { display: none; }
}
@media (max-width: 960px) {
  .report-layout { grid-template-columns: minmax(0, 1fr); gap: var(--space-6); }
}
/* 1150px 이하(태블릿·휴대폰): 한 학생을 두 줄로 쌓는다. 이름 | 리포트 상태 | 동작, 그 아래 제출 · 정답률 · 숙제 · 등원 · 결석(값이 없는 칸은 걷는다).
   사이드바 옆 종이 안쪽이 약 900px보다 좁으면 여덟 칸이 들어가지 않아 리포트 상태·동작이 표 밖으로 밀리기 때문이다. */
@media (max-width: 1150px) {
  #report-results .table-wrap > table { min-width: 0; }
  .report-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .report-table tbody { display: block; }
  .report-table tr { display: flex; flex-wrap: wrap; align-items: center; gap: 2px var(--space-3); padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--app-rule); }
  .report-table tr:last-child { border-bottom: 0; }
  .report-table tr::after { content: ''; order: 2; flex-basis: 100%; }
  .report-table td { display: block; height: auto; padding: 0; border: 0; text-align: left; }
  .report-table td.r-name { order: 0; flex: 1 1 0; min-width: 0; white-space: normal; }
  .report-table td.r-report, .report-table td.row-action { order: 1; }
  .report-table td:is(.r-submit, .r-score, .r-homework, .r-attend, .r-absent) { order: 3; color: var(--app-muted); font-size: var(--text-xs); }
  .report-table td.none { display: none; }
  .report-table td.r-submit::before { content: '제출 '; }
  .report-table td.r-score::before { content: '정답률 '; }
  .report-table td.r-homework::before { content: '숙제 '; }
  .report-table td.r-attend::before { content: '등원 '; }
  .report-table td.r-absent::before { content: '결석 '; }
  .report-table .submit-cell { vertical-align: middle; gap: var(--space-1); }
  .report-table .submit-n { min-width: 0; }
  .report-table .progress { width: 3rem; }
}
@media (max-width: 760px) {
  .report-stats .report-metrics > div { grid-template-columns: minmax(0, 1fr); gap: 2px; padding: var(--space-2) 0; }
}
.person-row { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) 0; border-bottom: 1px solid var(--app-rule); }
.person-row > a { display: flex; align-items: center; gap: var(--space-3); flex: 1; }
.person-row form { margin-left: auto; }
.timeline-item { display: block; position: relative; padding: 0 0 var(--space-8) var(--space-6); border-left: 1px solid var(--app-border); margin-left: var(--space-1); }
.timeline-item h3 { margin: var(--space-2) 0; }
.timeline-item p { font-size: var(--app-body); color: var(--app-muted); }
.timeline-dot { position: absolute; left: -5px; top: var(--space-1); width: 9px; height: 9px; background: var(--app-muted); border: 2px solid var(--app-surface); border-radius: var(--app-radius-round); }

/* Learning, review and media */
.step { font-weight: var(--weight-semibold); color: var(--app-muted); margin-right: var(--space-2); }
.question-editor { display: grid; grid-template-columns: 35px 1.1fr 1.1fr 1.4fr var(--app-control-height); align-items: center; gap: var(--space-3); border-top: 1px solid var(--app-border); padding: var(--space-3) 0; }
.question-editor:first-child { margin-top: var(--space-4); }
.question-index { font-size: var(--text-sm); color: var(--app-muted); }
.question-editor .question-note { grid-column: 1 / -1; margin: 0; font-size: var(--text-sm); color: var(--app-muted); }
.question-editor .check-badge { color: var(--app-warn); font-weight: var(--weight-medium); }
.question-editor.needs-check input[name=expected] { border-color: var(--app-warn); box-shadow: 0 0 0 1px var(--app-warn); }
.heading-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); justify-content: flex-end; }
.answer-key { border: 1px solid var(--app-border); border-radius: var(--app-radius-panel); padding: var(--space-4); margin-bottom: var(--space-4); display: grid; gap: var(--space-3); }
.answer-key[hidden] { display: none; }
.answer-key-range { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
.answer-key-actions { display: flex; justify-content: flex-end; gap: var(--space-2); flex-wrap: wrap; }
.answer-key-list { margin: 0; padding-left: var(--space-5); font-size: var(--text-sm); }
.answer-key-list:empty { display: none; }
.link-button { background: none; border: 0; padding: 0; color: var(--app-text); text-decoration: underline; font: inherit; min-height: var(--app-control-height); }
/* 목록 한 줄은 --app-row 이상이다(직원 40px, 학생·학부모 52px). */
.key-row { display: flex; gap: var(--space-4); align-items: center; min-height: var(--app-row); border-bottom: 1px solid var(--app-border); padding: var(--space-2) 0; font-size: var(--app-body); flex-wrap: wrap; }
.key-row a { margin-left: auto; }
.result-banner { background: var(--app-ground); border: 1px solid var(--app-border); border-radius: var(--app-radius-panel); display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); padding: var(--space-4) var(--space-5); margin-bottom: var(--space-5); }
.result-banner p { color: var(--app-muted); font-size: var(--text-sm); margin-top: var(--space-1); }
.result-banner strong { font-size: var(--text-xl); color: var(--app-text); text-align: right; font-variant-numeric: tabular-nums; }
.result-banner strong small { font-weight: var(--weight-regular); }
.answer-row { display: flex; gap: var(--space-4); padding: var(--space-4) 0; border-bottom: 1px solid var(--app-border); }
.answer-row:last-child { border-bottom: 0; }
/* Georgia의 옛 숫자형은 01을 o1처럼 보이게 하므로 문항 번호는 본문 글꼴의 고정 폭 숫자로 쓴다. */
.answer-number { font: var(--weight-semibold) var(--text-base) var(--font-sans); font-variant-numeric: lining-nums tabular-nums; color: var(--app-text); min-width: 50px; }
.answer-number small { font: var(--text-xs) var(--font-sans); margin-top: var(--space-2); }
.answer-content { flex: 1; min-width: 0; }
.choices { display: flex; gap: var(--space-3); border: 0; padding: 0; margin: 0; flex-wrap: wrap; }
.choices legend { margin-bottom: var(--space-2); }
.choices label { position: relative; }
.choices input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.choices span { display: grid; place-items: center; width: var(--app-control-height); height: var(--app-control-height); border: 1px solid var(--app-field); border-radius: var(--app-radius-control); font-size: var(--text-base); }
.choices input:checked + span { background: var(--app-primary); color: var(--app-inverse); border-color: var(--app-primary); }
.choices input:focus-visible + span { outline: 3px solid var(--focus); outline-offset: 3px; }
.submitted-answer { font-size: var(--app-body); white-space: pre-wrap; overflow-wrap: anywhere; margin-bottom: var(--space-3); }
.strategy-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-3); margin: var(--space-4) 0; }
.strategy-grid > div { display: flex; gap: var(--space-3); align-items: center; background: var(--app-ground); border-radius: var(--app-radius-panel); padding: var(--space-3); }
.strategy-grid b { font: var(--text-xl) var(--font-editorial); color: var(--app-text); }
.strategy-grid span { font-size: var(--text-sm); font-weight: var(--weight-semibold); }
.strategy-grid small { font-weight: var(--weight-regular); }
.upload-form { border: 1px dashed var(--app-field); border-radius: var(--app-radius-panel); background: var(--app-ground); padding: var(--space-4); margin: var(--space-4) 0; }
.video-item { border-top: 1px solid var(--app-border); padding-top: var(--space-4); margin-top: var(--space-4); }
.video-item p { margin-bottom: var(--space-3); }
video { display: block; width: 100%; max-height: 420px; background: var(--app-text); border-radius: var(--app-radius-panel); margin-bottom: var(--space-4); }
.feedback { background: var(--app-ground); padding: var(--space-4); border-radius: var(--app-radius-panel); }
.feedback p { white-space: pre-wrap; margin: var(--space-2) 0 0; }
.task-card { display: flex; gap: var(--space-4); justify-content: space-between; min-height: var(--app-row); padding: var(--space-3) 0; border-top: 1px solid var(--app-border); }
.task-card h3 { margin: var(--space-1) 0; }
.task-card p { font-size: var(--app-body); color: var(--app-muted); margin-bottom: var(--space-1); }
.task-card > div { min-width: 0; }
.task-card small { font-variant-numeric: tabular-nums; }
.task-card > div:last-child { text-align: right; min-width: 95px; }
.task-card > .badge { align-self: flex-start; }
.task-card:first-child { border-top: 0; padding-top: 0; }
.task-arrow { display: block; color: var(--app-muted); margin-top: var(--space-2); }
/* 학생·학부모 학습 현황(자녀 고르기 포함): 오늘 줄, 그리고 한 줄 전체가 링크인 목록.
   줄은 왼쪽에 굵은 이름과 회색 설명 줄, 오른쪽에 상태 배지다. 휴대폰에서도 배지를 오른쪽에 둔다. */
.learn-today { margin-bottom: var(--space-5); font-variant-numeric: tabular-nums; }
.learn-today p { margin-top: var(--space-1); }
.learn-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); min-height: var(--app-row); padding: var(--space-2) 0; border-top: 1px solid var(--app-rule); }
.learn-row:first-child { border-top: 0; }
.learn-row > span:first-child { min-width: 0; overflow-wrap: anywhere; }
.learn-row small { display: block; margin-top: 2px; color: var(--app-muted); font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
.learn-row > span + span { flex-shrink: 0; max-width: 50%; display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: var(--space-1); }
.learn-row > span + span .badge + .badge { margin-left: 0; }
.learn-row .icon { color: var(--app-muted); }
a.learn-row:hover b { text-decoration: underline; text-underline-offset: 3px; }
/* 최근 결과의 여섯 번째부터는 접어 둔다. 접힌 줄도 목록 한 줄과 같은 높이와 윗줄이다. */
.learn-more > summary { display: list-item; align-content: center; min-height: var(--app-row); border-top: 1px solid var(--app-rule); }
.attendance-log { min-height: var(--app-row); padding: var(--space-2) 0; border-bottom: 1px solid var(--app-border); display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); font-size: var(--app-body); }
.attendance-log small { text-align: right; }
.qr-panel { text-align: center; }
.qr-panel img { display: block; width: 100%; max-width: 280px; height: auto; aspect-ratio: 1; margin: var(--space-4) auto; background: var(--app-surface); }
.qr-panel p { color: var(--app-muted); font-size: var(--text-sm); }
/* 등·하원과 출석 화면(키오스크)은 손가락으로 누르고 조금 떨어져 읽으므로 업무 밀도보다 크게 둔다. */
.check-in-panel { --app-control-height: 3rem; --app-input-height: 3rem; --app-body: var(--text-base); max-width: 580px; margin: var(--space-10) auto; text-align: center; padding: var(--space-12); font-size: var(--app-body); }
.check-in-panel p { margin-bottom: var(--space-6); }
.check-in-panel .button { justify-self: stretch; }
.instant-qr { display: block; max-width: 100%; height: auto; margin: var(--space-5) auto; background: var(--app-surface); }
.pairing-code { font-size: var(--text-2xl); letter-spacing: .1em; overflow-wrap: anywhere; }
.kiosk-panel { max-width: 700px; }
.kiosk-phone { margin-top: var(--space-8); padding-top: var(--space-8); border-top: 1px solid var(--app-border); text-align: left; }
/* 번호 숫자는 조금 떨어져서도 읽히게 크게 둔다. 라벨 입력란 공통 규칙(과 휴대폰 16px 규칙)보다 구체적이어야 덮이지 않는다. */
.kiosk-phone input:not([type=checkbox]):not([type=radio]):not([type=file]) { font-size: var(--text-2xl); letter-spacing: .3em; text-align: center; font-variant-numeric: tabular-nums; }
.kiosk-match { display: grid; grid-template-columns: 1fr auto auto; gap: var(--space-3); align-items: center; padding: var(--space-4) 0; border-top: 1px solid var(--app-border); text-align: left; }
.kiosk-match b { font-size: var(--text-xl); }
.answer-text { white-space: pre-wrap; overflow-wrap: anywhere; max-width: 420px; }
.prose { white-space: pre-wrap; overflow-wrap: anywhere; color: var(--app-text); }
/* 가입·학원 안내 관리: 학원 코드 한 줄, 회원 연결 신청 표(한 신청이 한 묶음 tbody), 줄 아래로 펼치는 승인 양식, 접어 둔 학원 안내. */
.code-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-4); margin-bottom: var(--space-6); }
.code-bar > h2 { margin: 0; }
.code-bar > .code-state { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-3); flex: 1 1 24rem; margin: 0; }
.code-bar .pairing-code { font-size: var(--text-xl); font-weight: var(--weight-bold); }
.admission-table .ad-who { min-width: 8rem; }
.admission-table .ad-who b { display: block; font-weight: var(--weight-semibold); }
.admission-table .ad-who small, .admission-table .ad-review small { display: block; margin-top: 0; color: var(--app-muted); font-size: var(--text-xs); }
.admission-table .ad-message { min-width: 14rem; overflow-wrap: anywhere; }
.admission-table .ad-review { min-width: 9rem; }
.admission-table .ad-action summary { list-style: none; }
.admission-table .ad-action summary::-webkit-details-marker { display: none; }
.admission-table tr.ad-detail { display: none; }
.application-row:has(details[open]) > tr.ad-detail { display: table-row; }
.application-row:has(details[open]) > tr > td { background: var(--app-ground); }
/* 펼침 단추: 닫혀 있으면 '확인·승인', 펼치면 '접기'. */
.ad-action .when-open, .ad-action details[open] .when-closed { display: none; }
.ad-action details[open] .when-open { display: inline; }
/* 줄 사이 선은 신청 묶음 사이에만 둔다(펼친 줄과 그 신청 줄은 한 덩어리). */
.application-row > tr > td { border-bottom: 0; }
.application-row + .application-row { border-top: 1px solid var(--app-rule); }
.ad-more { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); gap: var(--space-6); padding: var(--space-2) var(--space-1) var(--space-4); }
.ad-more h3 { margin-bottom: var(--space-2); font-size: var(--app-body); }
.ad-more .student-options { background: var(--app-surface); }
.ad-more .field-note a { text-decoration: underline; text-underline-offset: 3px; }
.option-group { flex-basis: 100%; color: var(--app-muted); font-size: var(--text-xs); font-weight: var(--weight-semibold); }
.info-panel { margin-top: var(--space-6); }
.info-panel > summary { display: list-item; align-content: center; }
.info-panel > summary .helper { margin-left: var(--space-2); font-weight: var(--weight-regular); }
.info-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-4); }
/* 960px 이하에서는 한 신청을 쌓는다: 역할 · 신청자 | 상태 | 동작, 확인 정보, 신청 시각, 처리. 승인 대기의 빈 처리 칸은 숨긴다. */
@media (max-width: 960px) {
  .admission-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .admission-table tbody.application-row { display: block; }
  .admission-table tr.ad-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto; grid-template-areas: "role who status action" "msg msg msg msg" "when when when when" "review review review review"; align-items: center; gap: var(--space-1) var(--space-2); padding: var(--space-2) var(--space-3); }
  .admission-table tr.ad-row > td { height: auto; padding: 0; }
  .admission-table .ad-role { grid-area: role; }
  .admission-table .ad-who { grid-area: who; min-width: 0; }
  .admission-table .ad-status { grid-area: status; }
  .admission-table .ad-action { grid-area: action; }
  .admission-table .ad-message { grid-area: msg; min-width: 0; }
  .admission-table .ad-when { grid-area: when; color: var(--app-muted); font-size: var(--text-xs); }
  .admission-table .ad-when::before { content: '신청 '; }
  .admission-table .ad-review { grid-area: review; min-width: 0; color: var(--app-muted); font-size: var(--text-xs); }
  .admission-table .ad-review > .nowrap::before { content: '처리 '; }
  .admission-table td.ad-review:has(> .muted:only-child) { display: none; }
  .application-row:has(details[open]) > tr.ad-detail { display: block; }
  .application-row:has(details[open]) > tr { background: var(--app-ground); }
  .admission-table tr.ad-detail > td { display: block; height: auto; padding: 0 var(--space-3); }
  .ad-more { grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
  .info-grid { grid-template-columns: minmax(0, 1fr); }
}
.youtube-player { display: block; width: 100%; aspect-ratio: 16/9; min-height: 200px; border: 0; border-radius: var(--app-radius-panel); margin: var(--space-4) 0; background: var(--app-text); }
.lecture-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); gap: var(--space-4); margin-top: var(--space-4); }
.lecture-card { display: flex; flex-direction: column; overflow: hidden; background: var(--app-surface); border: 1px solid var(--app-border); border-radius: var(--app-radius-panel); }
.lecture-thumb { position: relative; display: block; aspect-ratio: 16/9; background: var(--app-text); }
.lecture-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.lecture-play { position: absolute; inset: 0; margin: auto; width: 56px; height: 56px; display: grid; place-items: center; border-radius: var(--app-radius-round); background: var(--app-scrim); color: var(--app-inverse); font-size: var(--text-lg); transition: background var(--duration-fast) var(--ease-standard), transform var(--duration-fast) var(--ease-standard); }
.lecture-thumb:hover .lecture-play, .lecture-thumb:focus-visible .lecture-play { background: var(--app-primary); transform: scale(1.08); }
.lecture-card .youtube-player { margin: 0; border-radius: 0; min-height: 0; }
.lecture-body { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-3) var(--space-4) var(--space-4); }
.lecture-body h3 { margin: 0; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
.lecture-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin: 0; font-size: var(--text-sm); color: var(--app-muted); }
.lecture-meta .badge { background: var(--app-neutral-bg); color: var(--app-muted); white-space: normal; }
.lecture-card-inline { flex-direction: row; max-width: 560px; }
.lecture-card-inline .lecture-thumb { flex: 0 0 200px; }
.lecture-card-inline .lecture-body { justify-content: center; padding: var(--space-4); }
.lecture-card-inline .lecture-play { width: 44px; height: 44px; font-size: var(--text-md); }
.lecture-card-inline:has(iframe) { flex-direction: column; max-width: 720px; }
@media (max-width: 760px) { .lecture-card-inline { flex-direction: column; } .lecture-card-inline .lecture-thumb { flex-basis: auto; } }
.lecture-classes { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-2); }
/* 강의 보관함 표: 강의마다 한 묶음(tbody). 작은 썸네일 · 강의 · 단원 · 공개 반 칩 · 연결 수 · 등록 · 편집(details[id]).
   편집을 열면 아래 줄에 재생 자리와 연결 주소, 공개 반 양식, 연결된 과제·문항이 펼쳐진다(상담 표와 같은 펼침). */
.lecture-table td { padding-block: var(--space-2); }
.lecture-table .l-thumb { width: 5.5rem; padding-right: 0; }
.lecture-mini { position: relative; display: block; width: 4.5rem; aspect-ratio: 16/9; border-radius: 4px; overflow: hidden; background: var(--app-text); }
.lecture-mini img { display: block; width: 100%; height: 100%; object-fit: cover; }
.lecture-mini .lecture-play { width: 1.5rem; height: 1.5rem; font-size: 0.625rem; }
.lecture-mini:hover .lecture-play, .lecture-mini:focus-visible .lecture-play { background: var(--app-primary); }
.lecture-table .l-title { min-width: 14rem; overflow-wrap: anywhere; }
.lecture-table .l-title strong { font-weight: var(--weight-semibold); }
.lecture-table .l-topic { min-width: 6rem; }
.lecture-table td.chips { width: 30%; }
.lecture-table .l-links { white-space: nowrap; }
.lecture-table .l-day small { display: block; margin-top: 0; color: var(--app-muted); font-size: var(--text-xs); }
.row-edit > summary { list-style: none; }
.row-edit > summary::-webkit-details-marker { display: none; }
.lecture-table tr.lecture-detail { display: none; }
.lecture-item:has(details[open]) > tr.lecture-detail { display: table-row; }
.lecture-item:has(details[open]) > tr > td { background: var(--app-ground); }
.lecture-item > tr > td { border-bottom: 0; }
.lecture-item + .lecture-item { border-top: 1px solid var(--app-rule); }
.lecture-more { display: grid; grid-template-columns: minmax(0, 18rem) minmax(0, 1fr) minmax(0, 18rem); gap: var(--space-6); padding: var(--space-1) var(--space-1) var(--space-3); }
.lecture-more h3 { margin: 0 0 var(--space-2); font-size: var(--app-body); }
.lecture-player .lecture-thumb { border-radius: var(--app-radius-panel); overflow: hidden; }
.lecture-player .youtube-player { margin: 0; min-height: 0; }
.lecture-preview { max-width: 28rem; }
.lecture-preview label { margin-top: var(--space-3); font-size: var(--text-sm); }
.lecture-preview .helper { margin-top: var(--space-1); color: var(--app-muted); }
.lecture-more .lecture-classes { margin-top: 0; align-items: flex-start; }
.class-picks { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 10rem), 1fr)); gap: 0 var(--space-3); width: 100%; }
.class-picks .check { min-width: 0; }
.class-picks .class-chip { margin: 0; white-space: normal; }
.lecture-uses { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
.lecture-uses .class-chip { margin-left: var(--space-1); }
.lecture-uses small { display: block; color: var(--app-muted); font-size: var(--text-xs); }
/* 학생 강의: 반마다 반 색 칩 제목과 카드 묶음. */
.lecture-group + .lecture-group { margin-top: var(--space-4); }
.lecture-group h2 { margin: 0; font-size: var(--app-body); }
.lecture-group h2 .class-chip { margin: 0; font-size: inherit; white-space: normal; }
.lecture-group .lecture-grid { margin-top: 0; }
/* 1150px 이하(노트북·태블릿)에서는 단원·등록 열을 걷고 강의 아래 한 줄(단원 · 등록일)로 옮긴다. */
.lecture-table .l-sub, .lecture-table .l-sub-links { display: none; }
@media (max-width: 1150px) {
  .lecture-table .l-topic, .lecture-table .l-day { display: none; }
  .lecture-table .l-title { min-width: 10rem; }
  .lecture-table .l-sub { display: block; margin-top: 0; color: var(--app-muted); font-size: var(--text-xs); }
  .lecture-more { grid-template-columns: minmax(0, 16rem) minmax(0, 1fr); }
  .lecture-more > :last-child { grid-column: 1 / -1; }
}
/* 960px 이하에서는 한 강의를 썸네일 | 강의(단원·등록·연결 한 줄) | 편집, 그 아래 공개 반 칩으로 쌓고, 펼친 줄은 한 단이다.
   종이 안쪽이 표 열을 다 담지 못해 표 안에서 가로로 밀리기 때문이다(상담 표와 같은 폭). */
@media (max-width: 960px) {
  .lecture-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .lecture-table tbody.lecture-item { display: block; }
  .lecture-table tr.lecture-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "thumb title action" "classes classes classes"; align-items: center; gap: var(--space-1) var(--space-2); padding: var(--space-2) var(--space-3); }
  .lecture-table tr.lecture-row > td { height: auto; padding: 0; width: auto; min-width: 0; }
  .lecture-table .l-thumb { grid-area: thumb; }
  .lecture-table .l-title { grid-area: title; }
  .lecture-table .l-sub-links { display: inline; }
  .lecture-table td.chips { grid-area: classes; }
  .lecture-table .row-action { grid-area: action; }
  .lecture-table .l-links { display: none; }
  .lecture-item:has(details[open]) > tr.lecture-detail { display: block; }
  .lecture-table tr.lecture-detail > td { display: block; height: auto; padding: 0 var(--space-3); }
  .lecture-more { grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
}
@media (max-width: 760px) {
  .class-picks { display: flex; flex-wrap: wrap; gap: 0 var(--space-3); padding-inline: var(--space-3); }
  .class-picks .class-chip { white-space: nowrap; }
}
.assignment-lectures { margin-bottom: var(--space-6); }
.assignment-lectures .lecture-grid { margin-top: 0; }
.assignment-sheet { margin-bottom: var(--space-6); }
.sheet-pages { display: grid; gap: var(--space-4); }
.sheet-pages img { display: block; width: 100%; max-width: 900px; height: auto; margin: 0 auto; border: 1px solid var(--app-border); border-radius: var(--app-radius-panel); background: var(--app-surface); }
#sheet-upload { margin: var(--space-4) 0 0; }
.question-count { display: flex; align-items: center; gap: var(--space-2); }
.question-count label { display: flex; align-items: center; gap: var(--space-2); white-space: nowrap; }
.question-count label input[type=number] { width: 5.5rem; margin-top: 0; }
.explanation-player { margin-top: var(--space-5); }
.explanation-player > .helper { margin-top: var(--space-2); }

/* Feedback and help */
/* 알림 띠: 상태색 쌍의 바탕과 글자. 저장은 완료 녹색, 오류는 적색, 데모 안내는 황갈색. */
.demo-banner, .notice { padding: var(--space-2) var(--space-3); border-radius: var(--app-radius-control); font-size: var(--app-body); font-weight: var(--weight-medium); margin-bottom: var(--space-4); }
.demo-banner { background: var(--app-warn-bg); color: var(--app-warn); padding: var(--space-1) var(--space-3); margin-bottom: var(--space-3); font-size: var(--text-xs); }
.notice { background: var(--app-ok-bg); color: var(--app-ok); }
.notice.error { background: var(--app-bad-bg); color: var(--app-bad); }
/* 화면 위 저장 알림: 닫기 버튼은 알림 영역(role) 밖에 두어 낭독 문구에 섞이지 않게 한다. */
.notice-row { position: relative; }
.notice-row > .notice { padding-right: var(--space-12); }
.notice-close { position: absolute; top: 0; right: 0; display: grid; place-items: center; width: var(--app-control-height); height: 100%; min-height: var(--app-control-height); border: 0; background: none; color: var(--app-muted); }
.notice-close .icon { width: 16px; height: 16px; }
.notice-close:hover { color: var(--app-text); }
.checkin-alerts { position: fixed; right: var(--space-6); bottom: var(--space-6); z-index: var(--z-alerts); width: min(22rem, calc(100vw - 2 * var(--space-4))); max-height: 45vh; overflow-y: auto; display: grid; gap: var(--space-3); }
.checkin-alerts:empty { display: none; }
.checkin-alert { background: var(--app-surface); border: 1px solid var(--app-border); border-radius: var(--app-radius-panel); box-shadow: var(--app-shadow-float); padding: var(--space-4); font-size: var(--text-sm); }
.checkin-alert header { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-2); }
.checkin-alert header small, .checkin-alert li small { color: var(--app-muted); }
.checkin-alert ul { list-style: none; margin: var(--space-3) 0; padding: 0; display: grid; gap: var(--space-2); }
.checkin-alert li a { overflow-wrap: anywhere; }
.checkin-alert li small { display: block; }
/* 빈 화면: 비어 있는 이유와 다음 행동을 글로. 글자로 대신한 아이콘은 두지 않는다. */
.empty { padding: var(--space-8) var(--space-4); text-align: center; color: var(--app-muted); }
.empty h3, .empty h2 { margin-bottom: var(--space-1); color: var(--app-text); font-size: var(--text-md); }
.empty .button { margin-top: var(--space-4); }
.muted, .helper { color: var(--app-muted); }
.helper { font-size: var(--text-sm); }
.helper a { color: var(--app-text); text-decoration: underline; text-underline-offset: 3px; }
summary { cursor: pointer; color: var(--app-text); font-weight: var(--weight-semibold); min-height: var(--app-control-height); }
.error-panel { max-width: 700px; margin: var(--space-16) auto; padding: var(--space-6); }
.error-panel p { margin: var(--space-2) 0 var(--space-5); }
.error-panel .brand { margin-bottom: var(--space-6); }
/* 도움말 첫 화면: 처음 쓰는 분(번호 붙은 할 일 다섯 칸), 메뉴별로 찾기(사이드바 묶음 머리 줄, 쓰는 사람 역할 색 라벨,
   안내 절 링크와 안내 이름), 아래 과제 상태 읽는 법(좁은 단)과 자주 묻는 질문(넓은 단). */
.help-path { margin-top: var(--space-4); }
.help-path h3 { font-size: var(--text-sm); color: var(--app-muted); }
.help-path ol { list-style: none; counter-reset: help-path; display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: var(--space-3) var(--space-4); margin: var(--space-2) 0 0; padding: 0; }
.help-path li { counter-increment: help-path; display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: var(--space-2); align-content: start; }
.help-path li::before { content: counter(help-path); grid-row: span 2; display: grid; place-items: center; width: 1.5rem; height: 1.5rem; border-radius: var(--app-radius-round); background: var(--app-neutral-bg); color: var(--app-text); font-size: var(--text-xs); font-weight: var(--weight-semibold); font-variant-numeric: tabular-nums; }
.help-path a { color: var(--app-text); font-weight: var(--weight-semibold); text-decoration: underline; text-underline-offset: 3px; }
.help-path li span { font-size: var(--text-sm); color: var(--app-muted); }
.help-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.65fr); gap: var(--space-6); align-items: start; }
.help-steps { list-style: none; counter-reset: help-step; margin: 0; padding: 0; }
.help-steps li { counter-increment: help-step; position: relative; padding: var(--space-6) 0 var(--space-6) var(--space-12); border-bottom: 1px solid var(--app-border); }
.help-steps li:first-child { padding-top: var(--space-1); }
.help-steps li:last-child { border-bottom: 0; padding-bottom: 0; }
.help-steps li::before { content: counter(help-step); position: absolute; left: 0; color: var(--app-muted); font-size: var(--text-lg); font-weight: var(--weight-semibold); }
.help-steps p { font-size: var(--app-body); margin-top: var(--space-3); color: var(--app-text); }
.help-layout a { color: var(--app-text); text-decoration: underline; text-underline-offset: 3px; }
.help-status { margin: 0; }
.help-status dt { margin-top: var(--space-4); }
.help-status dd { font-size: var(--text-sm); margin: var(--space-2) 0 0; color: var(--app-text); }
.help-faq details { border-top: 1px solid var(--app-border); padding: var(--space-3) 0; }
.help-faq details:last-child { padding-bottom: 0; }
.help-faq summary { font-size: var(--app-body); display: list-item; align-content: center; }
.help-faq p { margin-top: var(--space-3); font-size: var(--text-sm); color: var(--app-text); }
/* 화면 사진으로 보는 사용 안내 */
.guide { max-width: 960px; }
.guide h3 { margin-top: var(--space-6); }
.guide p, .guide ul { margin-top: var(--space-3); color: var(--app-text); }
.guide .table-wrap { margin-top: var(--space-4); }
/* 안내 표는 글만 있어 좁은 화면에서도 가로 스크롤 대신 줄을 바꾼다. */
.guide .table-wrap > table:not(.todo-table) { min-width: 0; }
.guide-facts { display: grid; grid-template-columns: max-content 1fr; gap: var(--space-2) var(--space-4); margin: var(--space-4) 0 0; }
.guide-facts dt { font-weight: var(--weight-semibold); }
.guide-facts dd { margin: 0; color: var(--app-text); }
.guide-shot { margin-top: var(--space-4); }
.guide-shot.compact { max-width: 640px; }
.guide-shot img { display: block; width: 100%; height: auto; border: 1px solid var(--app-border); border-radius: var(--app-radius-panel); }
.guide-shot figcaption { margin-top: var(--space-2); font-size: var(--text-sm); color: var(--app-muted); }
/* 휴대폰 사진은 휴대폰 화면에서 한 줄에 하나씩 보여 글자가 작아지지 않게 한다. */
.guide-phones { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--space-4); max-width: 720px; }
.guide th[scope=row] { min-width: 6.5em; }
.guide-caution { padding: var(--space-2) var(--space-3); border-radius: var(--app-radius-control); background: var(--app-warn-bg); color: var(--app-warn); }
.guide a { color: var(--app-text); text-decoration: underline; text-underline-offset: 3px; }
.guide-toc ol { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-6); margin: var(--space-4) 0 0; padding-left: var(--space-5); font-size: var(--text-sm); }
/* 도움말 첫 화면: 사진 안내 카드와 메뉴별 표 */
.help-guides { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: var(--space-3); margin-top: var(--space-3); }
.help-guides a { display: grid; gap: var(--space-1); align-content: start; padding: var(--space-4); border: 1px solid var(--app-border); border-radius: var(--app-radius-panel); color: var(--app-text); transition: border-color var(--duration-fast) var(--ease-standard); }
.help-guides a:hover { border-color: var(--app-field); }
.help-guides span { font-size: var(--text-sm); color: var(--app-muted); }
/* 일반 표의 좁은 화면 최소 폭(32rem)을 덮는다. 좁은 화면에서는 쓰는 사람·자세한 안내 열을 걷고 안내 링크를 하는 일 아래에 둔다. */
.help-menu .table-wrap > table.help-table:not(.todo-table) { min-width: 0; }
.help-menu th[scope=row] { width: 12rem; padding: var(--space-3); }
.help-menu th[scope=row] a, .help-guide a { color: var(--app-text); text-decoration: underline; text-underline-offset: 3px; }
.help-menu .help-group th { padding: var(--space-2) var(--space-3); background: var(--app-ground); color: var(--app-muted); font-size: var(--text-xs); font-weight: var(--weight-semibold); text-align: left; }
.help-roles { width: 15rem; }
.help-roles .badge { margin: 1px var(--space-1) 1px 0; }
.help-guide { width: 13rem; }
.help-guide small { display: block; margin-top: 2px; color: var(--app-muted); font-size: var(--text-xs); }

/* 입구 화면(로그인·회원가입): 업무 화면 언어의 덜 촘촘한 단계(body.density-comfortable). 틀 위에 양식 하나만 흰 상자로 둔다.
   로그인 아래 학원 소개는 공개 사이트가 정식 공개될 때까지만 두는 것이라 상자 없이 윗줄로 나눈다. */
.public-shell main { max-width: var(--layout-public); padding-top: var(--space-12); }
.login-form, .signup-panel { max-width: 26rem; margin: 0 auto; padding: var(--space-8); }
.login-form .brand, .signup-panel .brand { margin-bottom: var(--space-6); }
.login-form .brand-mark, .signup-panel .brand-mark { width: 40px; height: 40px; }
.login-form h1 { font-size: var(--text-xl); font-weight: var(--weight-bold); margin-bottom: var(--space-4); }
.login-form .notice { margin-bottom: var(--space-4); }
.login-form .primary { margin-top: var(--space-2); }
.signup-link { display: flex; flex-wrap: wrap; align-items: center; column-gap: var(--space-2); margin-top: var(--space-4); color: var(--app-muted); }
.signup-link a { display: inline-flex; align-items: center; min-height: var(--app-control-height); color: var(--app-text); font-weight: var(--weight-semibold); text-decoration: underline; text-underline-offset: 3px; }
.demo-accounts { border-top: 1px solid var(--app-border); margin-top: var(--space-5); padding-top: var(--space-4); font-size: var(--text-sm); color: var(--app-muted); }
.demo-accounts p { margin-top: var(--space-1); }
.academy-intro { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 25rem); gap: var(--space-12); align-items: start; max-width: 60rem; margin: var(--space-16) auto 0; padding-top: var(--space-10); border-top: 1px solid var(--app-border); }
/* 화면의 h1은 양식의 '반가워요.'이고, 큰 문구(h2)는 업무 화면 제목보다 한 단계 크게(26px) 둔다. 줄은 낱말 사이에서 고르게 바꾼다. */
.academy-intro h2 { font-size: var(--text-2xl); font-weight: var(--weight-bold); text-wrap: balance; }
.academy-intro h3 { font-size: var(--text-lg); margin-top: var(--space-10); }
.academy-intro p { margin-top: var(--space-2); color: var(--app-muted); }
.intro-topics { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-4); }
.intro-topics span { padding: 2px var(--space-2); border-radius: 4px; background: var(--app-neutral-bg); color: var(--app-text); font-size: var(--text-sm); font-weight: var(--weight-medium); }
.principal-profile { max-width: 25rem; }
.principal-profile img { display: block; width: 100%; height: auto; border-radius: var(--app-radius-panel); }
.principal-profile figcaption { margin-top: var(--space-2); font-size: var(--text-sm); color: var(--app-muted); }
.welcome-intro { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); gap: var(--space-8); align-items: center; margin-bottom: var(--space-8); background: var(--navy-950); color: var(--app-inverse); border-radius: var(--app-radius-panel); overflow: hidden; }
.welcome-intro > div { padding: var(--space-8); }
.welcome-intro p { color: var(--app-inverse-muted); }
.welcome-intro h2 { font-size: var(--text-3xl); margin-bottom: var(--space-5); }
.welcome-intro img { width: 100%; height: auto; display: block; }

/* Keyboard and responsive behavior */
.sr-only, .skip:not(:focus) { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.skip:focus { position: fixed; z-index: var(--z-skip); background: var(--app-surface); color: var(--app-text); padding: var(--space-4); }
@media (min-width: 1550px) {
  main, .shell main { padding-top: var(--space-8); }
}
@media (max-width: 1150px) {
  main { padding: var(--space-6) var(--space-6) var(--space-10); }
  .shell main { padding-inline: var(--space-6); }
  .card-grid, .strategy-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* 오른쪽 새 상담 신청을 표 아래로 내려 처리할 일 표가 종이 폭을 다 쓴다. */
  .dashboard-main.has-aside { grid-template-columns: minmax(0, 1fr); }
  .person-row { flex-wrap: wrap; }
  .question-editor { grid-template-columns: 30px 1fr 1fr var(--app-control-height); }
  .question-editor > label:nth-of-type(3) { grid-column: 2 / 4; }
  .question-editor > .remove-question { grid-column: 4; grid-row: 1; }
  .help-layout { grid-template-columns: minmax(0, 1fr); }
  /* 상담 표의 상담 일시·작성자 열은 걷는다(펼친 줄의 상담 메모 위에 있다). 여덟 칸이 종이 안에 들어가지 않기 때문이다. */
  .consult-table .c-when, .consult-table .c-author { display: none; }
  .consult-table .c-next { min-width: 10rem; }
  /* 복습 과제 표는 한 과제를 두 줄로 쌓는다: 과제 | 동작, 그 아래 반 · 마감 · 제출 · 채점 대기 · 미제출 · 정답률.
     수업일과 값이 없는 칸(—)은 걷는다. 종이 안쪽이 약 900px보다 좁으면 아홉 칸이 들어가지 않기 때문이다. */
  .assign-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .assign-table tbody { display: block; }
  .assign-table tr { display: flex; flex-wrap: wrap; align-items: center; gap: 2px var(--space-3); padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--app-rule); }
  .assign-table tr:last-child { border-bottom: 0; }
  .assign-table tr::after { content: ''; order: 2; flex-basis: 100%; }
  .assign-table td { display: block; height: auto; padding: 0; border: 0; text-align: left; }
  .assign-table td.a-title { order: 0; flex: 1 1 0; min-width: 0; }
  .assign-table td.row-action { order: 1; }
  .assign-table td.a-class, .assign-table td.a-due, .assign-table td.count { order: 3; color: var(--app-muted); font-size: var(--text-xs); }
  .assign-table td.a-day, .assign-table td.none { display: none; }
  .assign-table td.a-due::before { content: '마감 '; }
  .assign-table td.a-submit::before { content: '제출 '; }
  .assign-table td.a-pending::before { content: '채점 대기 '; }
  .assign-table td.a-missing::before { content: '미제출 '; }
  .assign-table td.a-rate::before { content: '정답률 '; }
  .assign-table .submit-cell { vertical-align: middle; gap: var(--space-1); }
  .assign-table .submit-n { min-width: 0; }
  .assign-table .progress { width: 3rem; }
}
/* 태블릿 폭에서는 사이드바 옆 종이 안쪽이 약 700px보다 좁아진다. 보조 단(320px)을 옆에 두면 본문 단이 글자 몇 개 폭으로 줄어들므로 한 단으로 쌓는다. */
@media (max-width: 960px) {
  .two-col, .academy-intro { grid-template-columns: minmax(0, 1fr); }
  /* 처리할 일 표는 한 행을 두 줄로 쌓는다: 상태·무엇·이동 링크, 그 아래 반·수·기한. 빈 ::after가 줄을 바꾼다.
     종이 안쪽이 700px보다 좁으면 여섯 칸 표의 반 이름이 세 줄로 접히기 때문이다. */
  .todo-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .todo-table tbody { display: block; }
  .todo-table tr { display: flex; flex-wrap: wrap; align-items: center; gap: 2px var(--space-2); padding: var(--space-2) 0; border-bottom: 1px solid var(--app-rule); }
  .todo-table tr::after { content: ''; order: 4; flex-basis: 100%; }
  .todo-table tr:last-child { border-bottom: 0; padding-bottom: 0; }
  .todo-table td { display: block; height: auto; padding: 0; border: 0; text-align: left; }
  .todo-table td:nth-child(1) { order: 1; }
  .todo-table td:nth-child(2) { order: 2; flex: 1 1 0; min-width: 0; }
  .todo-table td:last-child { order: 3; }
  .todo-table td:nth-child(3) { order: 5; }
  .todo-table td.count { order: 6; }
  .todo-table td.due { order: 7; }
  .todo-table td:nth-child(3), .todo-table td.count, .todo-table td.due { color: var(--app-muted); font-size: var(--text-xs); }
  .todo-table td.due:not(:empty)::before { content: '기한 '; }
  /* 앞으로 7일도 같은 폭부터 날짜 한 줄에 날짜·과제 마감, 그 아래 수업·보강을 쌓는다. 머리글은 화면 낭독기에만 남긴다. */
  .week-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .week-table tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-1) var(--space-2); padding: var(--space-2) 0; border-bottom: 1px solid var(--app-rule); }
  .week-table tr:last-child { border-bottom: 0; }
  .week-table th[scope=row], .week-table td { display: block; width: auto; height: auto; padding: 0; border: 0; }
  .week-table td.count { grid-row: 1; grid-column: 2; color: var(--app-muted); font-size: var(--text-xs); }
  .week-table td.count:not(:empty)::before { content: '과제 마감 '; }
  .week-table td:not(.count) { grid-column: 1 / -1; }
  /* 상담 표는 한 상담을 쌓는다: 학생 | 상태 | 동작, 다음 조치(펼치기), 기한, 반 칩. 학생 탭은 다음 조치 | 상태 | 동작, 기한.
     종이 안쪽이 약 700px보다 좁으면 반 칩과 다음 조치가 들어갈 자리가 없어 표 안에서 가로로 밀리기 때문이다. */
  .consult-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .consult-table tbody.consult-item { display: block; }
  .consult-table tr.consult-row { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; grid-template-areas: "who status action" "next next next" "due due due" "classes classes classes"; align-items: center; gap: var(--space-1) var(--space-2); padding: var(--space-2) var(--space-3); }
  .consult-table.in-record tr.consult-row { grid-template-areas: "next status action" "due due due"; }
  .consult-table tr.consult-row > td { height: auto; padding: 0; }
  .consult-table .c-student { grid-area: who; }
  .consult-table .c-classes { grid-area: classes; }
  .consult-table .c-next { grid-area: next; min-width: 0; }
  .consult-table .c-status { grid-area: status; }
  .consult-table .c-action { grid-area: action; }
  .consult-table .c-due { grid-area: due; color: var(--app-muted); font-size: var(--text-xs); white-space: normal; }
  .consult-table .c-due::before { content: '기한 '; }
  .consult-table .c-due small { display: inline; }
  .consult-table .c-due small::before { content: ' · '; }
  .consult-item:has(details[open]) > tr.consult-detail { display: block; }
  .consult-table tr.consult-detail > td { display: block; height: auto; padding: 0 var(--space-3); }
  .consult-more { grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
}
@media (max-width: 760px) {
  /* 학생 기록 머리는 한 단으로 쌓고 메모 남기기를 요약 아래에 둔다. 도구 막대의 검색칸은 한 줄을 다 쓴다. */
  .record-head { grid-template-columns: minmax(0, 1fr); grid-template-areas: "back" "title" "facts" "actions"; }
  .record-head > .heading-actions { justify-content: flex-start; margin-top: var(--space-2); }
  .toolbar-search { flex-basis: 100%; max-width: none; }
  .toolbar > label:not(.toolbar-search) { flex: 1 1 8rem; }
  .toolbar select { width: 100%; max-width: none; }
  /* 좁은 화면에서는 덜 중요한 열(아이디, 반)을 숨겨 상태 열이 표 밖으로 밀리지 않게 한다. */
  .wide-only { display: none; }
  .narrow-only { display: inline; }
  .board-times.narrow-only { display: block; color: var(--app-muted); }
  /* 출결 표는 한 학생을 두 줄로 쌓는다: 위에 이름·시각 | 상태 | 동작, 아래에 반 칩. 머리글은 화면 낭독기에만 남긴다. */
  .board-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); }
  .board-table tr.attendance-row { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: var(--space-1) var(--space-2); padding: var(--space-2) 0; border-bottom: 1px solid var(--app-rule); }
  .board-table tr.attendance-row > td { height: auto; padding: 0; border: 0; }
  .board-table tr.attendance-row > td.chips { grid-column: 1 / -1; order: 3; min-width: 0; width: auto; }
  /* 결석·보강 표는 한 결석을 쌓는다: 결석일·학생 | 상태, 반 칩·사유, 보강 일정, 동작. 빈 보강 일정·동작 칸은 숨긴다. */
  .absence-table tr.absence-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--space-1) var(--space-2); padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--app-rule); }
  .absence-table tr.absence-row > td { height: auto; padding: 0; border: 0; }
  .absence-table td.a-day { grid-area: 1 / 1; }
  .absence-table td.a-student { grid-area: 1 / 2; }
  .absence-table td.a-status { grid-area: 1 / 3; }
  .absence-table td.a-class { grid-area: 2 / 1; }
  .absence-table td.a-reason { grid-area: 2 / 2 / 3 / 4; min-width: 0; }
  .absence-table td.a-makeup { grid-area: 3 / 1 / 4 / 4; }
  .absence-table td.a-action { grid-area: 4 / 1 / 5 / 4; text-align: left; white-space: normal; }
  .absence-table.mine td.a-day { grid-area: 1 / 1 / 2 / 3; }
  .absence-table td.none { display: none; }
  .absence-table tr.makeup-row, .absence-table tr.makeup-row > td { display: block; }
  /* 종이책 숙제 표도 한 숙제를 두 줄로 쌓는다: 위에 기한·학생 | 상태 | 동작, 아래에 교재·범위와 반 칩·학생 완료 요약. */
  .homework-table tr.homework-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto; align-items: center; gap: var(--space-1) var(--space-2); padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--app-rule); }
  .homework-table tr.homework-row > td { height: auto; padding: 0; border: 0; }
  .homework-table tr.homework-row > td.book { grid-column: 1 / -1; order: 1; }
  .homework-facts.narrow-only { display: block; }
  /* 휴대폰에는 사이드바 대신 틀 위쪽에 로고와 이름·로그아웃을 두고, 그 아래 종이를 놓는다. */
  .sidebar { position: static; width: auto; padding: var(--space-3) var(--space-4) var(--space-2); display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; column-gap: var(--space-3); }
  .brand { font-size: var(--text-lg); }
  .brand-mark { width: 48px; height: 48px; }
  .brand small { font-size: .5625rem; }
  .sidebar .brand { min-height: var(--app-control-height); padding-inline: 0; }
  .sidebar .brand-mark { width: 40px; height: 40px; }
  .sidebar .profile .avatar { display: none; }
  .sidebar .profile { grid-row: 1; grid-column: 2; margin-top: 0; border-top: 0; padding-top: 0; gap: var(--space-1); text-align: right; }
  /* 직원(과 메뉴가 하나뿐인 가입 회원)은 사이드바 메뉴가 가로로 스크롤하는 줄이 된다. 선택한 메뉴는 넓은 화면과 같은 흰 면·네이비 글자·1px 테두리. */
  .sidebar nav { grid-column: 1 / -1; display: flex; overflow-x: auto; gap: var(--space-1); margin: var(--space-2) 0 0; padding-bottom: var(--space-2); padding-right: 1px; scrollbar-width: thin; }
  .sidebar nav a { padding: var(--space-2) var(--space-3); white-space: nowrap; flex-shrink: 0; }
  .sidebar .nav-group, .sidebar .nav-rule { display: none; }
  /* 학생·학부모는 사이드바 메뉴 대신 화면 아래에 붙은 탭 네 개와 더보기를 쓴다.
     맨 아래 내용과 키보드 초점이 탭에 가리지 않게 아래를 비워 둔다. 좁은 화면(375px 이하)에서는 메뉴 이름이 두 줄로 접혀 탭이 약 67px까지 높아지므로 탭 한 칸 높이에 16px을 더한다.
     sticky 대신 fixed인 것은, sticky 탭에 키보드 초점이 가면 Chrome이 스크롤 여백을 맞추려고 화면을 크게 내려 버리기 때문이다. */
  html.has-tabs .sidebar nav { display: none; }
  html.has-tabs .shell { padding-bottom: calc(var(--app-tabbar) + var(--space-4) + var(--space-2)); }
  html.has-tabs { scroll-padding-bottom: calc(var(--app-tabbar) + var(--space-4)); }
  .bottom-tabs { position: fixed; inset: auto 0 0; z-index: var(--z-navigation); display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); background: var(--app-surface); border-top: 1px solid var(--app-border); }
  /* 아이콘을 위쪽에 맞춰 두어, 좁은 화면에서 이름이 두 줄로 접힌 탭도 아이콘 줄이 어긋나지 않는다. */
  .bottom-tabs > a, .bottom-more > summary { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 2px; min-height: var(--app-tabbar); padding: 0.375rem 2px var(--space-1); color: var(--app-muted); font-size: 0.71875rem; font-weight: var(--weight-medium); line-height: 1.2; text-align: center; }
  .bottom-tabs :focus-visible { outline-offset: -3px; }
  /* 선택한 탭은 네이비 글자에 아이콘 뒤 옅은 네이비 면. 색만으로 구분하지 않게 면을 함께 둔다. */
  .bottom-tabs > a .icon, .bottom-more > summary .icon { width: 3rem; height: 1.75rem; padding: 0.25rem 0.875rem; border-radius: var(--app-radius-round); }
  .bottom-tabs > a.active, .bottom-more > summary.active { color: var(--app-primary); font-weight: var(--weight-semibold); }
  .bottom-tabs > a.active .icon, .bottom-more > summary.active .icon { background: var(--app-selected); }
  .bottom-more > summary { list-style: none; }
  .bottom-more > summary::-webkit-details-marker { display: none; }
  /* 펼친 더보기는 본문 글자색. 지금 화면이 더보기 안에 있으면(.active) 펼쳐도 네이비 현재 표시를 유지한다. */
  .bottom-more[open] > summary:not(.active) { color: var(--app-text); }
  /* 더보기는 탭 위에 뜨는 목록이다. 화면 위에 떠 있으므로 알림과 같은 그림자를 쓴다. */
  .bottom-more > div { position: absolute; right: var(--space-2); bottom: calc(100% + var(--space-2)); display: grid; gap: 2px; min-width: 12rem; padding: var(--space-1); background: var(--app-surface); border: 1px solid var(--app-border); border-radius: var(--app-radius-panel); box-shadow: var(--app-shadow-float); }
  .bottom-more > div > a { display: flex; align-items: center; gap: var(--space-3); min-height: 3rem; padding: var(--space-2) var(--space-3); border-radius: var(--app-radius-control); color: var(--app-text); font-size: var(--text-md); font-weight: var(--weight-medium); }
  .bottom-more > div > a .icon { color: var(--app-muted); }
  .bottom-more > div > a.active { color: var(--app-primary); background: var(--app-selected); font-weight: var(--weight-semibold); }
  .bottom-more > div > a.active .icon { color: inherit; }
  .sidebar nav.has-more { mask-image: linear-gradient(to right, currentColor calc(100% - var(--space-10)), transparent); }
  .shell { margin-left: 0; padding: 0 var(--space-2) var(--space-2); }
  .shell main { min-height: 0; padding: var(--space-5) var(--space-4) var(--space-8); }
  .page-heading { display: block; margin-bottom: var(--space-5); }
  .page-heading > .button, .page-heading > .inline-form, .page-heading > .heading-actions { margin-top: var(--space-4); }
  .page-heading > .heading-actions { justify-content: flex-start; }
  /* 16px보다 작은 입력값은 iOS가 누를 때 화면을 확대하므로 휴대폰에서만 모든 입력란을 16px로 키운다.
     라벨 안 입력란과 파일 선택은 더 구체적인 규칙이 작게 정하므로 같은 선택자로 함께 덮는다. */
  input, select, textarea, input[type=file], label input:not([type=checkbox]):not([type=radio]):not([type=file]), label select, label textarea { font-size: var(--text-base); }
  .dashboard-heading { padding-bottom: var(--space-2); }
  .dashboard-heading > .heading-actions { justify-content: flex-start; margin-top: var(--space-4); }
  .time-strip { padding: var(--space-3); }
  .time-strip > .section-heading, .todo > .section-heading { flex-wrap: wrap; }
  .table-wrap { margin: 0; }
  .table-wrap > table:not(.todo-table):not(.board-table) { min-width: 32rem; }
  td, th[scope=row] { padding: var(--space-1) var(--space-2); }
  th { padding: var(--space-2); }
  .row-title { min-width: 150px; }
  .two-col, .card-grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-5); }
  .form-grid { grid-template-columns: minmax(0, 1fr); }
  .form-actions { align-items: stretch; flex-direction: column; }
  .form-actions > .inline-form { justify-content: flex-end; }
  .strategy-grid { gap: var(--space-2); }
  .strategy-grid > div { padding: var(--space-3); }
  .answer-row { gap: var(--space-3); }
  .answer-number { min-width: 40px; }
  .choices { gap: var(--space-2); }
  .result-banner { padding: var(--space-4); display: block; }
  .result-banner strong { display: block; text-align: left; margin-top: var(--space-3); }
  .task-card { flex-direction: column; gap: var(--space-3); }
  .task-card > div:last-child { display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap; text-align: left; }
  .task-arrow { margin: 0 0 0 auto; }
  .question-editor { grid-template-columns: 25px minmax(0, 1fr) var(--app-control-height); }
  .question-editor > label, .question-editor > label:nth-of-type(3) { grid-column: 2; }
  .question-editor > .remove-question { grid-column: 3; }
  .question-editor .question-index { grid-row: 1; }
  .public-shell main { padding: var(--space-4); }
  .login-form, .signup-panel { padding: var(--space-6) var(--space-5); }
  .academy-intro { margin-top: var(--space-10); padding-top: var(--space-8); gap: var(--space-8); }
  .welcome-intro { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .welcome-intro > div { padding: var(--space-6); }
  .welcome-intro h2 { font-size: var(--text-2xl); }
  .check-in-panel { margin: var(--space-3) auto; padding: var(--space-8) var(--space-5); }
  .error-panel { margin: var(--space-4) auto; }
  footer { padding: var(--space-5) var(--space-4); gap: var(--space-2) var(--space-4); }
  .help-layout { gap: var(--space-5); }
  .help-menu th[scope=row] { width: 6.5rem; }
  .help-menu .help-inline.narrow-only { display: block; margin-top: var(--space-1); color: var(--app-text); font-size: var(--text-sm); text-decoration: underline; text-underline-offset: 3px; }
  .help-steps li { padding-left: var(--space-10); }
  .checkin-alerts { left: var(--space-4); right: var(--space-4); bottom: var(--space-4); width: auto; }
}
@media print {
  .skip, .sidebar, .demo-banner, .checkin-alerts, nav, .public-shell > footer { display: none !important; }
  .shell { margin-left: 0; padding: 0; }
  main, .public-shell main, .shell main { max-width: none; min-height: 0; padding: 0; border: 0; border-radius: 0; }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; transition: none !important; animation: none !important; }
}
/* 문제 은행 */
.bank-pages { grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); }
.bank-page-card { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-3); border: var(--border-width) solid var(--app-border); border-radius: var(--app-radius-panel); background: var(--app-surface); color: inherit; text-decoration: none; }
.bank-page-card img { width: 100%; height: auto; border: var(--border-width) solid var(--app-border); border-radius: var(--app-radius-panel); }
.bank-editor { align-items: start; }
.crop-frame { width: 100%; height: auto; border: var(--border-width) solid var(--app-border); border-radius: var(--app-radius-panel); background: var(--app-surface); }
.figure-row { display: grid; grid-template-columns: 8rem 1fr; gap: var(--space-3); align-items: start; padding: var(--space-3) 0; border-top: var(--border-width) solid var(--app-border); }
.figure-row img { width: 100%; height: auto; border: var(--border-width) solid var(--app-border); border-radius: var(--app-radius-control); }
.figure-row input[type=number], [data-bbox-form] input[type=number] { width: 5.5rem; }
.problem-card { padding: var(--space-4); border: var(--border-width) solid var(--app-border); border-radius: var(--app-radius-panel); background: var(--app-surface); }
.problem-head, .problem-foot { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; font-size: var(--text-sm); color: var(--app-muted); }
.problem-head b { font-size: var(--text-base); color: var(--app-text); }
/* 카드 아래 줄은 footer 요소라 화면 바닥글의 넓은 여백을 받지 않게 윗선 아래 여백만 둔다. */
.problem-foot { padding: var(--space-3) 0 0; }
.problem-body { margin: var(--space-3) 0; white-space: pre-wrap; line-height: var(--leading-body); color: var(--app-text); }
.problem-body.preview { min-height: 3rem; padding: var(--space-3); border: var(--border-width) dashed var(--app-border); border-radius: var(--app-radius-panel); background: var(--app-ground); }
.problem-figure { display: block; max-width: 100%; height: auto; margin: var(--space-2) 0; }
.problem-choices { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: var(--space-2); margin: var(--space-3) 0; padding: 0; list-style: none; }
.choice-mark { color: var(--app-muted); }
.tag { padding: 0 var(--space-2); border-radius: var(--app-radius-round); background: var(--app-neutral-bg); font-size: var(--text-xs); }
/* 과정 색 라벨(학교급마다 한 색)과 난이도 단계(하 → 상으로 짙어지는 회청색과 막대 1~3칸). 둘 다 배지 모양이고 글자와 함께다. */
.course-elementary { background: var(--app-course-elementary-bg); color: var(--app-course-elementary); }
.course-middle { background: var(--app-course-middle-bg); color: var(--app-course-middle); }
.course-high { background: var(--app-course-high-bg); color: var(--app-course-high); }
.course-essay { background: var(--app-course-essay-bg); color: var(--app-course-essay); }
.badge.level { display: inline-flex; align-items: center; gap: var(--space-1); }
.level-low { background: var(--app-level-low-bg); color: var(--app-level-low); }
.level-mid { background: var(--app-level-mid-bg); color: var(--app-level-mid); }
.level-high { background: var(--app-level-high-bg); color: var(--app-level-high); }
.level-bars { display: inline-flex; align-items: flex-end; gap: 1px; height: 0.625rem; }
.level-bars > span { width: 3px; border-radius: 1px; background: currentColor; opacity: 0.3; }
.level-bars > span:nth-child(1) { height: 40%; }
.level-bars > span:nth-child(2) { height: 70%; }
.level-bars > span:nth-child(3) { height: 100%; }
.level-low .level-bars > span:nth-child(-n+1), .level-mid .level-bars > span:nth-child(-n+2), .level-high .level-bars > span { opacity: 1; }
/* 문제 은행 목록: 자료별로 묶은 표(tbody). 한 문제가 한 줄이고, 문제 첫 줄(details[id])을 펼치면 다음 줄에 수식·그림·선지를 그린 미리보기가 열린다.
   스크립트 없이 열리고, 즉시 필터로 표를 바꿔도 펼친 줄은 그대로다(app.js swapSection). */
.table-meta .bank-meta-end { display: inline-flex; align-items: center; gap: var(--space-3); }
.bank-views { display: inline-flex; gap: var(--space-1); }
.bank-cards { padding: var(--space-3); }
.tag-filter { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); }
#bank-tag:empty { display: none; }
/* 찾기 줄(검색·과정·단원·난이도·자료)과 건수 칩 줄(상태·해설)을 나눈다. 1440px 종이 안에 일곱 묶음이 한 줄에 들어가지 않아 아무 데서나 접히지 않게 한다. */
#bank-filter .toolbar-break { flex-basis: 100%; height: 0; margin-top: calc(var(--space-2) * -1); }
.bank-table .bank-group-head > th { padding-top: var(--space-3); color: var(--app-text); font-size: var(--text-sm); white-space: normal; }
.bank-table .bank-group-head a { font-weight: var(--weight-semibold); }
.bank-table .bank-group-head .muted { font-weight: var(--weight-regular); }
.bank-table .b-label a { font-weight: var(--weight-semibold); }
.bank-table .b-label small { display: block; margin-top: 0; color: var(--app-muted); font-size: var(--text-xs); }
.bank-table .b-body { width: 38%; min-width: 16rem; }
.bank-table .b-unit { min-width: 6rem; }
.bank-table .b-tags { min-width: 7rem; }
.bank-table a.tag { display: inline-block; margin: 1px var(--space-1) 1px 0; color: var(--app-text); text-decoration: none; white-space: nowrap; }
.bank-table a.tag:hover { text-decoration: underline; text-underline-offset: 2px; }
.bank-table tr.bank-detail { display: none; }
.bank-table tr.bank-row:has(details[open]) + tr.bank-detail { display: table-row; }
.bank-table tr.bank-row:has(details[open]) > td, .bank-table tr.bank-detail > td { background: var(--app-ground); }
.bank-table tr.bank-row:has(details[open]) > td { border-bottom: 0; }
.bank-table tr.bank-detail > td { height: auto; padding: 0 var(--space-3) var(--space-3); }
.bank-preview { max-width: 52rem; padding: var(--space-3) var(--space-4); border: var(--border-width) solid var(--app-border); border-radius: var(--app-radius-panel); background: var(--app-surface); }
.bank-preview .problem-body { margin-top: 0; }
.bank-preview .problem-figure { width: auto; max-height: 18rem; }
.bank-preview-foot { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); margin: 0; color: var(--app-muted); font-size: var(--text-sm); }
/* 자료 표: 올린 때 · 자료 · 과정 · 쪽 · 문제 확정(진행 막대) · 상태 · 올린 사람 · 처리 정보. */
.material-table .m-title { min-width: 14rem; }
.material-table .m-title small { margin-top: 0; }
.material-table .row-link:hover { text-decoration: underline; text-underline-offset: 3px; }
/* 760px 이하에서는 한 자료를 두 줄로 쌓는다: 자료 이름 | 상태, 그 아래 올린 때 · 과정 · 쪽 · 문제 확정. */
@media (max-width: 760px) {
  .material-table tbody { display: block; }
  .material-table tr { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-2); padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--app-rule); }
  .material-table tr::after { content: ''; order: 2; flex-basis: 100%; }
  .material-table td { display: block; height: auto; padding: 0; border: 0; }
  .material-table td.wide-only { display: none; }
  .material-table td.m-title { order: 0; flex: 1 1 0; min-width: 0; }
  .material-table td.m-state { order: 1; }
  .material-table td:is(.m-when, .m-course, .m-pages, .m-progress) { order: 3; color: var(--app-muted); font-size: var(--text-xs); }
}
/* 960px 이하에서는 한 문제를 쌓는다: 번호 · 과정 · 난이도 · 단원 | 상태, 그 아래 문제 첫 줄, 태그. 머리글은 화면 낭독기에만 남긴다. */
@media (max-width: 960px) {
  .bank-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .bank-table tbody, .bank-table tr.bank-group-head, .bank-table tr.bank-group-head > th { display: block; }
  .bank-table tr.bank-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-2); padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--app-rule); }
  .bank-table tr.bank-row::after { content: ''; order: 5; flex-basis: 100%; }
  .bank-table tr.bank-row:has(details[open]) { border-bottom: 0; background: var(--app-ground); }
  .bank-table tr.bank-row > td { display: block; width: auto; min-width: 0; height: auto; padding: 0; border: 0; }
  .bank-table .b-label { order: 1; }
  .bank-table .b-label small { display: inline; margin-left: var(--space-1); }
  .bank-table .b-course { order: 2; }
  .bank-table .b-level { order: 3; }
  .bank-table .b-unit { order: 4; flex: 1 1 0; color: var(--app-muted); font-size: var(--text-xs); }
  .bank-table .b-status { order: 4; }
  .bank-table .b-body { order: 6; flex-basis: 100%; }
  .bank-table .b-tags { order: 7; flex-basis: 100%; }
  .bank-table tr.bank-row > td.b-solution, .bank-table tr.bank-row > td.b-tags:empty { display: none; }
  .bank-table tr.bank-row:has(details[open]) + tr.bank-detail { display: block; }
  .bank-table tr.bank-detail > td { display: block; }
  .bank-preview { padding: var(--space-3); }
}
.page-canvas { position: relative; touch-action: none; user-select: none; }
.page-canvas img { display: block; width: 100%; height: auto; border: var(--border-width) solid var(--app-border); }
.bbox-box { position: absolute; box-sizing: border-box; border: 2px solid var(--app-bad); }
.bbox-box.figure { border-color: var(--focus); pointer-events: none; }
.bbox-label { position: absolute; top: 0; left: 0; padding: 0 var(--space-1); background: var(--app-bad); color: var(--app-inverse); font-size: var(--text-xs); }
.region-canvas { touch-action: auto; }
.bbox-box.region { pointer-events: auto; cursor: move; color: var(--app-bad); }
.bbox-box.figure.region { color: var(--focus); }
.bbox-box.figure .bbox-label { background: var(--focus); }
.region-handle { position: absolute; width: 14px; height: 14px; box-sizing: border-box; border: 2px solid currentColor; background: var(--app-surface); transform: translate(-50%, -50%); touch-action: none; }
.region-handle[data-edge=nw] { left: 0; top: 0; cursor: nwse-resize; }
.region-handle[data-edge=n] { left: 50%; top: 0; cursor: ns-resize; }
.region-handle[data-edge=ne] { left: 100%; top: 0; cursor: nesw-resize; }
.region-handle[data-edge=e] { left: 100%; top: 50%; cursor: ew-resize; }
.region-handle[data-edge=se] { left: 100%; top: 100%; cursor: nwse-resize; }
.region-handle[data-edge=s] { left: 50%; top: 100%; cursor: ns-resize; }
.region-handle[data-edge=sw] { left: 0; top: 100%; cursor: nesw-resize; }
.region-handle[data-edge=w] { left: 0; top: 50%; cursor: ew-resize; }
@media (pointer: coarse) { .region-handle { width: 24px; height: 24px; } }
#problem-region input[type=number] { width: 5.5rem; }
.bbox-select { position: absolute; box-sizing: border-box; border: 2px dashed var(--app-primary); background: var(--app-selection-overlay); pointer-events: none; }
@media (max-width: 760px) { .figure-row { grid-template-columns: 1fr; } }
.notification-message { white-space: pre-wrap; overflow-wrap: anywhere; line-height: var(--leading-body); padding: var(--space-4); background: var(--app-ground); border-radius: var(--app-radius-panel); }
/* 학부모 카톡 알림 발송 현황판: 머리 아래 한 줄, 종류 색 라벨, 알림마다 한 묶음(tbody)인 표와 실패 알림의 다시 보내기 펼침. */
.notify-facts .meter { margin-left: var(--space-1); }
.nk-attendance { background: var(--app-notify-attendance-bg); color: var(--app-notify-attendance); }
.nk-homework { background: var(--app-notify-homework-bg); color: var(--app-notify-homework); }
.nk-note { background: var(--app-notify-note-bg); color: var(--app-notify-note); }
.notify-meta { flex-wrap: wrap; gap: 0 var(--space-4); }
.notify-table .nf-to { white-space: nowrap; }
.notify-table .nf-child .class-chip, .notify-table .nf-sub .class-chip { margin: 1px 0 1px var(--space-1); }
.notify-table .nf-brief { min-width: 12rem; overflow-wrap: anywhere; }
.notify-table .nf-brief .row-link:hover { text-decoration: underline; text-underline-offset: 3px; }
.notify-table .nf-reason { display: block; margin-top: 2px; color: var(--app-muted); font-size: var(--text-xs); }
.notify-table .nf-sub { display: none; }
/* 1340px 이하에서는 학생 열을 걷고 받는 사람 아래 한 줄(학생 · 반 칩)로 옮긴다. */
@media (max-width: 1340px) {
  .notify-table .nf-child { display: none; }
  .notify-table .nf-sub { display: block; margin-top: 0; color: var(--app-muted); font-size: var(--text-xs); white-space: normal; }
}
.notify-table tr.notify-detail { display: none; }
.notify-item:has(details[open]) > tr.notify-detail { display: table-row; }
.notify-item:has(details[open]) > tr > td { background: var(--app-ground); }
.notify-item > tr > td { border-bottom: 0; }
.notify-item + .notify-item { border-top: 1px solid var(--app-rule); }
.notify-more { display: grid; grid-template-columns: minmax(0, 28rem) minmax(0, 1fr); gap: var(--space-6); padding: var(--space-1) var(--space-1) var(--space-3); }
.notify-more .notification-message { background: var(--app-surface); border: 1px solid var(--app-border); }
.notify-more form { margin-top: 0; gap: var(--space-2); align-items: flex-start; }
.table-more { margin: 0; padding: var(--space-2) var(--space-3); border-top: 1px solid var(--app-border); }
.notify-section > summary .muted { font-weight: var(--weight-regular); }
.notify-section > .two-col { margin-top: var(--space-3); }
.notify-settings form { max-width: var(--layout-form); }
.notify-templates { display: grid; gap: var(--space-1); margin: var(--space-2) 0 0; }
.notify-templates dt { margin-top: var(--space-2); font-weight: var(--weight-semibold); }
.notify-templates dd { margin: 0; padding: var(--space-2) var(--space-3); font-size: var(--text-sm); }
.notify-recipients { max-width: 40rem; }
/* 960px 이하에서는 한 알림을 종류 · 내용 · 상태, 그 아래 시각 · 받는 사람 · 학생(반 칩) · 동작으로 쌓는다. */
@media (max-width: 960px) {
  .notify-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .notify-table tbody.notify-item { display: block; }
  .notify-table tr.notify-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-2); padding: var(--space-2) var(--space-3); }
  .notify-table tr.notify-row::after { content: ''; order: 4; flex-basis: 100%; }
  .notify-table tr.notify-row > td { height: auto; padding: 0; min-width: 0; }
  .notify-table .nf-kind { order: 1; }
  .notify-table .nf-brief { order: 2; flex: 1 1 8rem; min-width: 0; }
  .notify-table .nf-status { order: 3; display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 0 var(--space-1); }
  .notify-table .nf-reason { margin-top: 0; }
  .notify-table .nf-time { order: 5; color: var(--app-muted); }
  .notify-table .nf-to { order: 6; white-space: normal; }
  .notify-table td.nf-child { display: block; order: 7; }
  .notify-table .nf-sub { display: none; }
  .notify-table .row-action { order: 8; margin-left: auto; }
  .notify-table .row-action:empty { display: none; }
  .notify-item:has(details[open]) > tr.notify-detail { display: block; }
  .notify-item:has(details[open]) > tr.notify-row { background: var(--app-ground); }
  .notify-item:has(details[open]) > tr.notify-row > td { background: none; }
  .notify-table tr.notify-detail > td { display: block; height: auto; padding: 0 var(--space-3); }
  .notify-more { grid-template-columns: minmax(0, 1fr); gap: var(--space-3); }
}
.report-metrics { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-3); margin: var(--space-5) 0; }
.report-metrics dd { margin: 0; font-weight: var(--weight-semibold); overflow-wrap: anywhere; }

/* 역량 진단·월간 역량 리포트 */
.competency-overview { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: var(--space-6); align-items: start; }
.competency-overview h2 { margin-bottom: var(--space-2); }
.radar-box { margin: 0; }
.radar { display: block; width: 100%; max-width: 420px; height: auto; margin: 0 auto; }
.radar-ring { fill: none; stroke: var(--app-border); }
.radar-axis { stroke: var(--app-border); }
.radar-label { fill: var(--app-text); font-size: 15px; font-weight: var(--weight-medium); }
.radar-target { fill: none; stroke: var(--app-chart-target); stroke-width: 1.5; stroke-dasharray: 5 4; }
.radar-now { fill: var(--app-selection-overlay); stroke: var(--app-primary); stroke-width: 2.5; }
.radar-now-dot { fill: var(--app-primary); }
.radar-before { fill: none; stroke: var(--app-field); stroke-width: 2; stroke-dasharray: 3 4; }
.radar-before-dot { fill: var(--app-surface); stroke: var(--app-field); stroke-width: 2; }
.competency-table td, .module-table td { vertical-align: middle; }
.numeric { font-variant-numeric: tabular-nums; white-space: nowrap; }
/* 개수 열은 오른쪽 정렬한다. 날짜·시각 열은 .numeric만 쓰고 왼쪽 정렬을 유지한다. */
td.count, th.count { text-align: right; }
.confirm-form { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.confirm-form select { min-height: var(--app-input-height); width: auto; }
.check-grid { display: flex; flex-wrap: wrap; gap: 0 var(--space-5); }
.skill-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: var(--space-5); }
.skill-grid legend, .outcome-set legend { font-weight: var(--weight-semibold); }
.skill-grid .check { align-items: flex-start; padding: var(--space-1) 0; }
.outcome-set { border-top: 1px solid var(--app-border); padding-top: var(--space-4); }
.outcome-options { display: flex; flex-wrap: wrap; gap: 0 var(--space-5); }
.set-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--space-3); }
.set-card { display: grid; gap: var(--space-1); padding: var(--space-4); border: 1px solid var(--app-border); border-radius: var(--app-radius-panel); color: var(--app-text); text-decoration: none; min-height: var(--app-control-height); }
.set-card:hover, .set-card:focus-visible { border-color: var(--app-field); background: var(--app-ground); }
.void-form summary { font-size: var(--text-sm); color: var(--app-muted); cursor: pointer; }
.report-section + .report-section { margin-top: var(--space-8); }
.report-section h2 small { display: inline; font-size: var(--text-sm); font-weight: var(--weight-regular); color: var(--app-muted); margin-left: var(--space-2); }
.report-shape { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr); gap: var(--space-6); align-items: center; }
.change { white-space: nowrap; }
/* 월간 역량 리포트 목록: 재원생마다 한 줄. 일곱 역량의 이번 달 단계 띠(머리글에 같은 순서의 첫 글자 연·수·추·공·논·함·해)는
   3단계(학년 목표) 이상 완료 녹색, 미만 대기 황갈색, 확정 전 회색 칸에 숫자를 함께 쓰고, 띠 전체를 '연산력 3단계, …'로 읽는다. */
.competency-board td small { display: block; }
.competency-board .rp-people { width: 100%; white-space: nowrap; }
.level-strip { display: grid; grid-template-columns: repeat(7, 1.5rem); gap: 2px; width: max-content; }
.level-strip > span { display: grid; place-items: center; height: 1.5rem; border-radius: 4px; background: var(--app-neutral-bg); color: var(--app-muted); font-size: var(--text-xs); font-weight: var(--weight-semibold); font-variant-numeric: tabular-nums; }
.level-strip > .lv-ok { background: var(--app-ok-bg); color: var(--app-ok); }
.level-strip > .lv-low { background: var(--app-warn-bg); color: var(--app-warn); }
.level-keys { margin-top: 2px; }
.level-keys > span { height: auto; background: none; }
.competency-head .record-title .badge { align-self: center; }
.reason-grid { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--space-3); }
.reason-tile { display: grid; gap: var(--space-1); padding: var(--space-3); border: 1px solid var(--app-field); border-radius: var(--app-radius-panel); }
.reason-tile strong { font-size: var(--text-xl); font-variant-numeric: tabular-nums; }
.reason-tile strong small { display: inline; font-size: var(--text-sm); font-weight: var(--weight-regular); margin-left: var(--space-1); }
.print-page { background: var(--app-ground); }
.print-sheet { max-width: 210mm; margin: var(--space-6) auto; padding: 14mm; background: var(--app-surface); border: 1px solid var(--app-border); }
.print-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: end; gap: var(--space-4); border-bottom: 2px solid var(--app-primary); padding-bottom: var(--space-3); margin-bottom: var(--space-6); }
.print-head h1 { margin: 0; }
.print-head dl { display: flex; gap: var(--space-2) var(--space-4); flex-wrap: wrap; margin: 0; }
.print-head dt { color: var(--app-muted); }
.print-head dd { margin: 0; font-weight: var(--weight-semibold); }
.print-draft { padding: var(--space-3) var(--space-4); border-radius: var(--app-radius-control); background: var(--app-warn-bg); color: var(--app-warn); font-weight: var(--weight-semibold); }
.print-actions { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; }
.print-plan { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-6); }
.print-plan dd { margin: 0 0 var(--space-2); }
.print-foot { display: flex; justify-content: space-between; gap: var(--space-4); margin-top: var(--space-10); padding: var(--space-3) 0 0; font-size: var(--text-sm); color: var(--app-muted); }
@media (max-width: 1150px) { .reason-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 760px) {
  /* 휴대폰: 리포트 목록은 한 학생을 학생 | 상태 | 동작, 반 칩, 단계 띠로 쌓는다. 머리글은 .board-table 규칙으로 화면 낭독기에만 남는다. */
  .competency-board tbody { display: block; }
  .competency-board tr { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; grid-template-areas: "who status action" "classes classes classes" "levels levels levels"; align-items: center; gap: var(--space-1) var(--space-2); padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--app-rule); }
  .competency-board tr:last-child { border-bottom: 0; }
  .competency-board tr > td { height: auto; padding: 0; border: 0; }
  .competency-board .rp-student { grid-area: who; }
  .competency-board .rp-status { grid-area: status; }
  .competency-board .rp-classes { grid-area: classes; }
  .competency-board .rp-classes .class-chip { white-space: normal; }
  .competency-board .rp-levels { grid-area: levels; }
  .competency-board .row-action { grid-area: action; }
  .competency-board .rp-people, .competency-board .rp-levels:not(:has(.level-strip)) { display: none; }
  .competency-overview, .report-shape, .print-plan { grid-template-columns: 1fr; }
  .reason-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .print-sheet { margin: 0; padding: var(--space-4); border: 0; }
}
@media print {
  @page { size: A4; margin: 10mm 12mm; }
  html, .print-page { background: #fff; }
  .print-sheet { max-width: none; margin: 0; padding: 0; border: 0; font-size: 12px; line-height: 1.5; }
  .print-sheet h2 { font-size: 15px; margin-bottom: var(--space-2); }
  .print-sheet .print-head { margin-bottom: var(--space-4); }
  .print-sheet th, .print-sheet td { height: auto; padding: var(--space-1) var(--space-2); font-size: 12px; }
  .print-sheet .report-metrics { grid-template-columns: 10em minmax(0, 1fr); margin: var(--space-2) 0; gap: var(--space-1) var(--space-3); }
  .print-sheet .reason-tile { padding: var(--space-2); }
  .print-sheet .reason-tile strong { font-size: var(--text-lg); }
  .print-sheet .print-foot { margin-top: var(--space-3); }
  .screen-only { display: none !important; }
  .print-sheet .report-section + .report-section { margin-top: var(--space-4); }
  .print-sheet .report-shape { grid-template-columns: 1fr 1.2fr; }
  .print-sheet .reason-grid { grid-template-columns: repeat(6, 1fr); }
  .print-sheet .print-plan { grid-template-columns: 1fr 1fr; }
  .print-sheet .radar { max-width: 260px; }
  .print-sheet .print-draft { padding: var(--space-2) var(--space-3); margin-bottom: var(--space-2); }
  .print-sheet .print-plan dd { margin-bottom: var(--space-1); }
}

/* 수업 진행(routine): 첫 화면은 반별 진행판, 반 화면은 데스크톱 학생 × 단계 표와 휴대폰 학생 카드.
   단계 수(.step-pill)는 그 단계를 끝낸 학생 / 수업한 학생이고 색은 모두 끝냄 녹색, 진행 중 황갈색, 아직 회색이다.
   반 화면의 칸은 상태 색 면(완료 녹색, 미완료 황갈색, 해당 없음 회색)에 기호·값을 함께 쓴다. 색은 기존 상태색 쌍만 쓴다. */
.routine-board-wrap { overflow-x: auto; }
.routine-board th, .routine-board td { padding-inline: var(--space-2); }
.routine-board th.step-head { width: 3.5rem; padding-inline: 2px; text-align: center; white-space: normal; line-height: 1.3; }
.routine-board th.step-head small { display: block; margin-top: 2px; font-size: inherit; }
.routine-board td.step-count { padding-inline: 2px; text-align: center; }
.routine-board td.class-cell { min-width: 9rem; }
.routine-board td.class-cell .class-chip { white-space: normal; }
.routine-board td.class-cell .badge { margin-left: var(--space-1); }
.routine-board .board-teacher { margin-top: 2px; color: var(--app-muted); font-size: var(--text-xs); }
.routine-board td.remaining { min-width: 6rem; color: var(--app-muted); font-size: var(--text-sm); }
.step-pill { display: inline-block; min-width: 2.5rem; padding: 0.125rem var(--space-1); border-radius: 4px; background: var(--app-neutral-bg); color: var(--app-muted); font-size: var(--text-sm); font-weight: var(--weight-semibold); line-height: 1.4; text-align: center; font-variant-numeric: tabular-nums; }
.step-pill.is-all { background: var(--app-ok-bg); color: var(--app-ok); }
.step-pill.is-some { background: var(--app-warn-bg); color: var(--app-warn); }
.step-pill.is-empty { background: none; }
.routine-table th .step-pill { display: block; width: fit-content; margin-top: var(--space-1); }
.routine-heading h1 .class-chip { margin: 0; padding: 0.125rem var(--space-2); font-size: inherit; white-space: normal; }
.routine-heading h1 .class-chip::before { width: 0.625rem; height: 0.625rem; }
.routine-progress .badge { margin-right: var(--space-1); }
.chip-link { text-decoration: none; }
.chip-link:hover .class-chip { text-decoration: underline; text-underline-offset: 3px; }
.routine-common-form { display: flex; flex-wrap: wrap; align-items: end; gap: var(--space-3); }
.routine-common-form > label { flex: 1 1 16rem; }
.routine-common-form > .button { flex-shrink: 0; }
.routine-common > .helper { margin-top: var(--space-2); }
.routine-table th, .routine-table td { white-space: nowrap; }
/* '모두 완료'가 있는 머리글과 없는 머리글의 단계 이름이 같은 줄에 오게 위로 맞춘다. */
.routine-table thead th { vertical-align: top; }
/* 칸 값은 '6/7'처럼 짧으므로 머리글을 두 줄로 접어 1100px에서도 표가 가로로 넘치지 않게 한다. */
.routine-table thead th.count { white-space: normal; }
.routine-table td.routine-cell-wrap { width: 11%; padding: 2px; }
.routine-cell { display: flex; align-items: center; min-height: var(--app-control-height); padding: var(--space-1) var(--space-2); border-radius: var(--app-radius-control); color: inherit; text-decoration: none; }
.routine-cell.state-done { background: var(--app-ok-bg); }
.routine-cell.state-partial { background: var(--app-warn-bg); }
.routine-cell.state-skipped { background: var(--app-neutral-bg); }
.routine-cell:hover { box-shadow: inset 0 0 0 1px var(--app-field); }
.routine-cell.is-open { outline: 2px solid var(--app-primary); outline-offset: -2px; }
.routine-mark.state-done { color: var(--app-ok); }
.routine-mark.state-partial { color: var(--app-warn); }
.routine-mark.state-skipped, .routine-mark.state-memo { color: var(--app-muted); }
.routine-absent { opacity: .6; }
.routine-number { display: inline-grid; place-items: center; min-width: 1.5em; height: 1.5em; border-radius: var(--app-radius-round); background: var(--app-neutral-bg); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
.routine-held { background: var(--app-warn-bg); border: 1px solid var(--app-warn); color: var(--app-warn); border-radius: var(--app-radius-control); padding: var(--space-2) var(--space-3); }
.routine-auto { margin: 0 0 var(--space-2); padding-left: var(--space-5); }
/* 상태 버튼이 곧 저장이다. 지금 상태는 채운 버튼(primary)으로 보인다. */
.routine-status { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.routine-status .button { white-space: nowrap; }
/* 머리글의 '모두 완료'는 짧은 단계 이름(티칭·GGSL)보다 넓어지지 않게 작게 둔다. 표는 데스크톱에서만 보인다. */
.routine-fill { margin-top: var(--space-1); }
.routine-fill .button { min-height: 1.75rem; padding: 0 var(--space-1); font-size: var(--text-xs); }
.routine-fill-student { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); margin-bottom: var(--space-3); }
/* 저장 결과 줄(role=status)은 비어 있어도 숨기지 않는다. 처음부터 있는 알림 영역이어야 첫 안내도 읽힌다. */
.routine-saved { margin: 0; }
.routine-saved:not(:empty) { margin-block: var(--space-1); }
.routine-step summary { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); min-height: var(--app-control-height); cursor: pointer; }
.routine-step + .routine-step { margin-top: var(--space-3); }
.routine-cards { display: none; }
.routine-card { display: block; border: 1px solid var(--app-border); border-radius: var(--app-radius-control); padding: var(--space-3); color: inherit; text-decoration: none; background: var(--app-surface); }
.routine-card-head { display: flex; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-1); }
.routine-dots { display: inline-flex; gap: var(--space-1); vertical-align: middle; }
.routine-dots i { width: 12px; height: 12px; border-radius: var(--app-radius-round); border: 1px solid var(--app-field); }
.routine-dots i.state-done { background: var(--app-ok); border-color: var(--app-ok); }
.routine-dots i.state-partial { background: var(--app-warn); border-color: var(--app-warn); }
.routine-dots i.state-skipped { background: var(--app-border); border-color: var(--app-border); }
.routine-dots i.state-memo { border-style: dashed; }
@media (max-width: 760px) {
  .routine-table-wrap { display: none; }
  .routine-cards { display: grid; gap: var(--space-2); }
  /* 진행판은 반마다 세 줄로 쌓는다: 반 칩·상태 / 시간·등원·남은 학생 / 단계 번호와 수 7칸. */
  .routine-board thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .routine-board tbody { display: block; }
  .routine-board tr { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-2); padding: var(--space-3) 0; border-bottom: 1px solid var(--app-rule); }
  .routine-board tr:last-child { border-bottom: 0; }
  .routine-board tr::after { content: ''; order: 3; flex-basis: 100%; }
  .routine-board tr::before { content: ''; order: 7; flex-basis: 100%; }
  .routine-board td { display: block; height: auto; padding: 0; border: 0; }
  .routine-board td.class-cell { order: 1; flex: 1 1 0; min-width: 0; white-space: normal; }
  .routine-board td.state { order: 2; }
  .routine-board td.time, .routine-board td.attendance { color: var(--app-muted); font-size: var(--text-xs); }
  .routine-board td.time { order: 4; }
  .routine-board td.time:has(> .muted) { display: none; }
  .routine-board td.attendance { order: 5; }
  .routine-board td.attendance::before { content: '등원 '; }
  .routine-board td.remaining { order: 6; flex: 1 1 0; min-width: 0; font-size: var(--text-xs); text-align: right; }
  .routine-board td.step-count { order: 8; flex: 1 1 0; min-width: 0; max-width: calc((100% - 6 * var(--space-2)) / 7); }
  .routine-board td.step-count:empty { display: none; }
  .routine-board td.step-count::before { content: attr(data-step); display: block; color: var(--app-muted); font-size: var(--text-xs); }
  .routine-board .step-pill { display: block; min-width: 0; padding-inline: 0; font-size: var(--text-xs); }
}
