/* Solist 공통 스타일
 *
 * 모든 화면이 이 파일 하나를 봐요. 색·간격·글자 크기를 여기서 바꾸면
 * 전체 화면에 같이 적용돼요. 페이지마다 복사해두면 반드시 어긋나요.
 */
* { margin: 0; padding: 0; box-sizing: border-box; }
  :root {
    --sidebar-bg: #f7f7f7; --sidebar-hover: #efefef; --sidebar-active: #eaeaea;
    --sidebar-text: #3a3a3a; --sidebar-text-muted: #b0b0b0;
    /* 회색이 너무 연해서 안 보인다는 피드백으로 두 단계 다 진하게 했어요 (2026-09-11).
       secondary #6b6b6b -> #545454, muted #ababab -> #7a7a7a.
       색이 진해지면 검은 상위 텍스트와 가까워져서, 같은 위계 글자는 크기를
       한 단계 키워 위계를 크기로도 보이게 했어요 (아래 항목들). */
    --text-primary: #0f0f0f; --text-secondary: #545454; --text-muted: #7a7a7a; --line: #f0f0f0;
    /* iBEX 포인트 컬러. 원본(ibex_attendance/ibex_grades)의 --teal 이에요.
       빨강·앰버는 경고/알림 의미가 붙은 색이라 포인트로 쓰지 않아요.
       화면 안의 작은 구역 제목(.section-title)에만 써요 — 여기저기 칠하면 포인트가 아니게 돼요. */
    --point: #0F4C5C;

    /* 화면 여백은 이 두 값 하나로 정해요 (2026-09-23 원장 지적: "메뉴마다 여백이 좀 다른 것 같아").
       예전엔 상단바 28, 본문 32, 목록 16 이 따로따로라 메뉴를 옮길 때마다 글자 줄이 움직였어요.
       **새 화면을 만들 때 숫자를 직접 적지 말고 이 변수를 쓰세요.** */
    --pad-x: 32px;     /* 왼쪽·오른쪽 줄 — 상단바 제목 · 목록 줄 · 상세 내용이 모두 이 줄에 맞아요 */
    --pad-top: 28px;   /* 상단바 아래 첫 내용까지의 높이 — 왼쪽 칸과 오른쪽 칸이 같은 높이에서 시작해요 */
  }
  body { font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif; display: flex; height: 100vh; overflow: hidden; -webkit-font-smoothing: antialiased; font-size: 11px; color: var(--text-primary); }

  /* NAVBAR — 왼쪽 검은 세로 바 (docs/decisions/navigation-bar.md · 원장 지정 2026-10-12)
     예전의 회색 사이드바(#f7f7f7 · 글자 메뉴)를 대신해요. 가장자리에서 10 띄운 떠 있는 막대 · 모서리 14 · 그림자 · 테두리 없음.
     고른 것: 흰 칸 + 검은 선 아이콘 / 나머지: 흰 선 아이콘 / 올리면 흐려지고 이름 말풍선 */
  .navbar { width: 64px; margin: 10px 0 10px 10px; height: calc(100vh - 20px); border-radius: 14px; background: #000; display: flex; flex-direction: column; align-items: center; flex-shrink: 0; position: relative; z-index: 40; user-select: none; }  /* 떠 있는 긴 막대 (2026-10-12) */
  .nb-logo { color: #fff; font-size: 13px; font-weight: 700; letter-spacing: -0.3px; padding: 20px 0 18px; flex-shrink: 0; }
  /* 맨 위 프로필 사진 — 얇은 흰 테두리로 검은 바 위에서도 또렷하게 (원장 지정 2026-10-12) */
  .navbar .nb-avatar { width: 34px; height: 34px; border-radius: 50%; border: 1.5px solid #fff; background: #2a2a2a; color: #fff; font-size: 13px; font-weight: 600; display: flex; align-items: center; justify-content: center; overflow: hidden; }
  .nb-menu { flex: 1; min-height: 0; width: 100%; overflow-y: auto; scrollbar-width: none; display: flex; flex-direction: column; align-items: center; gap: 6px; padding-bottom: 10px; }
  .nb-menu::-webkit-scrollbar { display: none; }
  .nb-foot { width: 100%; display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 6px 0 16px; flex-shrink: 0; }
  .nb-item { width: 40px; height: 40px; border-radius: 8px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; gap: 12px; color: #fff; cursor: pointer; transition: opacity 0.12s; }
  .nb-item:hover:not(.active) { opacity: 0.6; }
  .nb-item.active { background: #fff; color: #000; cursor: default; }
  .nb-ic { display: inline-flex; width: 21px; height: 21px; flex-shrink: 0; }
  .nb-label { display: none; font-size: 13px; white-space: nowrap; }
  .nb-tip { display: none; position: fixed; z-index: 60; transform: translateY(-50%); background: #000; color: #fff; font-size: 11px; padding: 5px 8px; border-radius: 5px; white-space: nowrap; pointer-events: none; }
  .nb-burger, .nb-dim { display: none; }
  /* 좁은 화면 — 바는 숨고 세 줄 단추 로 열어요. 열면 아이콘 옆에 이름까지 (폭은 내용만큼 · 화면의 80% 까지) */
  @media (max-width: 767px) {
    .navbar { position: fixed; left: 10px; top: 10px; bottom: 10px; height: auto; margin: 0; width: auto; max-width: 80vw; align-items: stretch; padding: 0 10px; transform: translateX(-120%); }
    .navbar:not(.open) { visibility: hidden; }
    .nb-logo { padding-left: 12px; }
    .nb-menu, .nb-foot { align-items: stretch; }
    .nb-item { width: auto; justify-content: flex-start; padding: 0 12px; }
    .nb-label { display: inline; }
      .nb-dim { display: block; position: fixed; inset: 0; z-index: 39; background: #000; opacity: 0; pointer-events: none; }
    .nb-burger { display: inline-flex; margin-right: 12px; cursor: pointer; color: var(--text-primary); }
    .nb-tip { display: none !important; }
  }
  .sidebar-academy { font-size: 10px; color: var(--sidebar-text-muted); margin-top: 2px; }
  .sidebar-user { display: flex; align-items: center; gap: 9px; }
  .user-info { flex: 1; min-width: 0; }
  /* 로그아웃은 글자로 보여줘요 (2026-09-30). 전엔 내 이름을 눌러야 나가졌는데, 그 사실이 화면에 안 보였어요 */
  .user-logout { font-size: 10px; color: var(--sidebar-text-muted); cursor: pointer; padding: 3px 4px; flex-shrink: 0; }
  .user-logout:hover { color: var(--text-primary); }
  .user-avatar img, .profile-photo img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; display: block; }
  /* 설정의 내 프로필 사진 — 사진이 없으면 이름 첫 글자 */
  .profile-photo { width: 56px; height: 56px; border-radius: 50%; background: var(--sidebar-active); display: flex; align-items: center; justify-content: center; font-size: 20px; font-weight: 600; color: var(--text-secondary, #545454); flex-shrink: 0; overflow: hidden; }
  .user-avatar { width: 22px; height: 22px; border-radius: 50%; background: #e8e8e8; display: flex; align-items: center; justify-content: center; font-size: 10px; color: #ababab; flex-shrink: 0; }
  .user-name { font-size: 11px; color: var(--text-primary); }
  .user-role { font-size: 10px; color: var(--sidebar-text-muted); margin-top: 1px; }

  /* MAIN */
  .main { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
  .topbar { height: 48px; display: flex; align-items: center; padding: 0 var(--pad-x); flex-shrink: 0; }
  .topbar-title { font-size: 13px; font-weight: 600; letter-spacing: -0.2px; }
  .topbar-right { margin-left: auto; display: flex; align-items: center; gap: 20px; }
  .topbar-btn { font-size: 11px; color: var(--text-muted); cursor: pointer; transition: color 0.12s; user-select: none; position: relative; }
  .topbar-btn:hover { color: var(--text-primary); }
  .notif-dot { position: absolute; top: -2px; right: -4px; width: 5px; height: 5px; border-radius: 50%; background: #e53e3e; }
  /* 머리글 알림 · 채팅 아이콘 (2026-10-13 · common.js mountHeaderIcons). 안 읽음이면 채운 검정 + 튀기 */
  .topbar-icon { display: inline-flex; align-items: center; color: var(--text-muted); }
  .topbar-icon.is-unread, .topbar-icon:hover { color: var(--text-primary); }
  .topbar-icon .notif-dot { display: none !important; }
  .attn-body { display: inline-flex; transform-origin: 50% 100%; }
  /* Attention Bounce — 앱 components/Attention.js 와 같은 박자 (6초 한 묶음 중 앞 1.02초).
     준비 0.32~0.42초 4% 눌림 → 0.66초 위로 11px → 0.83초 살짝 아래 + 착지 8% 눌림 → 1.02초 제자리 */
  .attn { animation: attn-bounce 6s ease-in-out infinite; }
  @keyframes attn-bounce {
    0%, 5.3% { transform: none; }
    6.2% { transform: scale(1.04, 0.96); }
    7% { transform: none; }
    11% { transform: translateY(-11px); }
    13.8% { transform: translateY(1.4px) scale(1.087, 0.92); }
    16% { transform: translateY(0.5px) scale(1.02, 0.98); }
    17%, 100% { transform: none; }
  }
  @media (prefers-reduced-motion: reduce) { .attn { animation: none; } }

  /* 알림 목록 — 헤더 '알림' 을 누르면 그 아래로 내려와요 (2026-09-17 원장 결정).
     떠 있는 목록은 .picker-list 와 같은 방식이에요: 흰 배경 + 0.5px 선만,
     박스·그림자 없음 (가이드 0-1). 새 패턴이 아니라 기존 패턴의 오른쪽 정렬 변형이에요.
     .main 에 overflow:hidden 이 걸려 있어서 absolute 로는 잘려요 — fixed 로 띄워요. */
  /* 사방 테두리로 또렷하게 구분해요 (2026-09-17 원장 요청 — 어디까지가 알림 칸인지
     안 보였어요). 검색칸·글 칸(가이드 0-4 예외)과 같은 회색 테두리를 써요. */
  /* 2026-10-13 원장 지정 — 오른쪽 끝에서 밀려 들어오는 판 (앱 알림 · 채팅과 같은 방향).
     들어오기 · 나가기 모두 320ms Apple 곡선(모션 가이드 0절 EASE). 뒤 화면은 어둡게 덮지 않아요 (앱 채팅 판과 같아요).
     그림자 없이 왼쪽 0.5px 선만 (PC 가이드 0-1 박스 금지) */
  .notif-panel { position: fixed; top: 0; right: 0; bottom: 0; width: 380px; max-width: 100vw; z-index: 200; background: #fff;
    border-left: 0.5px solid #d0d0d0; display: flex; flex-direction: column;
    transform: translateX(105%); visibility: hidden; transition: transform 320ms cubic-bezier(0.25, 0.1, 0.25, 1), visibility 0s linear 320ms; }
  .notif-panel.open { transform: none; visibility: visible; transition: transform 320ms cubic-bezier(0.25, 0.1, 0.25, 1), visibility 0s; }
  @media (prefers-reduced-motion: reduce) { .notif-panel, .notif-panel.open { transition: none; } }
  .notif-head { display: flex; align-items: center; justify-content: space-between; padding: 16px 18px 10px; font-size: 15px; font-weight: 700; color: var(--text-primary); }
  .notif-close { font-size: 22px; line-height: 1; cursor: pointer; color: var(--text-primary); padding: 2px 4px; }
  .notif-close:hover { opacity: 0.6; }
  .notif-list { flex: 1; overflow-y: auto; padding: 0 4px; }
  .notif-item { display: flex; align-items: flex-start; gap: 10px; padding: 13px 14px; }
  .notif-body { flex: 1; min-width: 0; cursor: pointer; }
  .notif-title { font-size: 12px; color: var(--text-primary); margin-bottom: 3px; }
  .notif-text { font-size: 11px; color: var(--text-secondary); line-height: 1.5; word-break: break-word; }
  .notif-time { font-size: 10px; color: var(--text-muted); margin-top: 4px; }
  /* 안 읽은 줄 표식. 채팅 안읽음(.chat-unread)과 같은 빨강이에요 — 회색 배경은
     가이드 0-5 에서 "고른 것" 의 표시라 뜻이 겹쳐요. 삭제가 아니라 표시예요 (0-6 예외). */
  .notif-new { display: inline-block; width: 5px; height: 5px; border-radius: 50%; background: #e53e3e; margin-right: 6px; vertical-align: middle; }
  .notif-empty { padding: 28px 14px; text-align: center; font-size: 11px; color: var(--text-muted); }
  .notif-foot { display: flex; justify-content: flex-end; padding: 12px 14px; }

  /* BODY */
  .body-wrap { flex: 1; display: flex; overflow: hidden; }

  /* 목록 패널 */
  .list-panel { width: 288px; padding-right: 12px; display: flex; flex-direction: column; flex-shrink: 0; padding-top: var(--pad-top); }

  /* 정확히 반반 (질문 게시판) — 두 칸이 화면을 똑같이 나눠요 */
  .split-half > .list-panel { width: auto; flex: 1 1 0; }
  .split-half > .detail-panel { flex: 1 1 0; }
  /* 정확히 3등분 (공지사항) — 목록·상세·중요 공지가 화면을 똑같이 나눠요 */
  .split-thirds > .list-panel { width: auto; flex: 1 1 0; }
  .split-thirds > .detail-panel { flex: 1 1 0; }
  .split-thirds > .notice-important { width: auto; flex: 1 1 0; }
  /* 탭 안에서 균등하게 칸을 나눠요 (수업 기본정보·보충·휴강 2분할 / 공지·자료 3분할)
     칸을 패널 높이만큼 늘려서, 칸 사이 구분선이 채팅 화면처럼 아래까지 이어지게 해요. */
  .col-split { display: flex; gap: 28px; align-items: stretch; min-height: calc(100vh - 240px); }
  .col-split > .col { flex: 1 1 0; min-width: 0; }
  .col-split > .col + .col { padding-left: 40px; }
  /* 상세 화면 2·3분할: 위쪽 가로선을 두고 세로 구분선이 거기 닿게 해요 (채팅 화면과 동일).
     제목(panel-title) 바로 아래에서 가로선이 시작되고, 칸 사이 세로선이 그 선까지 올라가 만나요. */
  #viewDetail > .col-split { margin-top: 22px; }
  #viewDetail > .col-split > .col { padding-top: 18px; }
  /* 수업 화면(탭 안 분할): 탭 밑줄을 그 가로선으로 삼아, 세로 구분선이 탭 밑줄에 닿게 해요.
     탭 아래 여백을 없애고 칸을 그 위치까지 끌어올린 뒤, 내용만 안쪽 여백으로 내려요. */
  .tabs.lesson-tabs, .tabs.detail-tabs { margin-bottom: 0; }
  .lesson-tabs ~ .tab-panel, .detail-tabs ~ .tab-panel { padding-top: 18px; }
  .lesson-tabs ~ .tab-panel > .col-split, .detail-tabs ~ .tab-panel > .col-split { margin-top: -18px; }
  .lesson-tabs ~ .tab-panel > .col-split > .col, .detail-tabs ~ .tab-panel > .col-split > .col { padding-top: 18px; }
  /* 화면 상단 탭(.tabs) 아래에서 칸을 나눌 때도 같게 맞춰요 (결제 관리·출석부 외출 일정).
     .tabs 는 아래 여백이 28px 이라, 그만큼 끌어올려야 세로 구분선이 탭 밑줄에 닿아요 — 가이드 7번(2026-09-13). */
  .tabs ~ .tab-panel > .col-split { margin-top: -28px; }
  .tabs ~ .tab-panel > .col-split > .col { padding-top: 18px; }
  /* 단체 일정: 대상 고르는 체크 목록. 반의 '+학생 추가'와 같은 형식(박스 없이 줄로). 길면 스크롤. */
  .bulk-picklist { max-height: 220px; overflow-y: auto; }
  .bulk-picklist .empty-note { font-size: 11px; color: var(--text-muted); padding: 8px 0; }
  .list-search { padding: 0 var(--pad-x) 16px; }
  /* 검색칸은 채팅 입력칸처럼 상자로. 단 테두리는 회색으로 둬요(글자색 계열). */
  .search-input { width: 100%; font-size: 11px; font-family: inherit; color: var(--text-primary); border: 1px solid #d0d0d0; border-radius: 8px; outline: none; padding: 7px 11px; background: transparent; transition: border-color 0.15s; }
  .search-input:focus { border-color: var(--text-muted); }
  .search-input::placeholder { color: #d0d0d0; }
  /* .add-btn 은 없앴어요 (2026-09-17) — 목록 맨 위 버튼을 1급(.btn-1st)으로 올렸어요 */
  /* 목록 맨 위의 "학생 추가 / 공지 작성" 버튼 — 1급으로 올렸어요 (2026-09-17 원장 요청).
     .btn-1st 는 inline-flex 라 글자만큼만 차지해요. 목록 칸 안에서 숨 쉴 자리를 줘요.
     예전 .add-btn 은 목록과 0.5px 선으로 나뉘어 있었는데, 채운 버튼은 그 자체로
     구분되니 선을 따로 두지 않아요. */
  /* align-self 가 없으면 목록 칸(세로 flex)이 버튼을 칸 폭 전체로 늘려요.
     여백은 폼의 1급 버튼과 같은데도 덩치가 커 보였던 이유예요 (2026-09-17 원장 지적). */
  .list-panel .btn-1st.list-add { margin: 0 var(--pad-x) 12px; align-self: flex-start; }

  /* 상담 예약 · 질문 게시판 · 공지사항의 좌측은 **같은 폭**이에요 (2026-09-17 원장 요청 —
     화면을 오갈 때 왼쪽 칸이 들쭉날쭉하면 통일감이 깨져요).
     기준은 "상담 좌측(420px)보다 20% 긴 정도" 라서 500px 으로 뒀어요.
     1~12월 월 탭도 이 폭 안에 한 줄로 들어가요 (month-tabs 로 여백을 좁혔어요).
     학생·선생님 같은 이름 목록 화면은 260px 그대로예요 — 넓힐 이유가 없어요. */
  .list-panel.wide-list { width: 528px; }

  /* ── 목록의 '추가' 버튼: 검은 정사각형 + 더하기 아이콘 ──
     2026-09-17 원장 요청. 글자('학생 추가')를 정사각형 아이콘 버튼으로 바꿨어요.
     자리는 검색칸 **왼쪽** 이에요 — 목록을 훑다가 새로 만들려면 늘 같은 자리에 있어야 해요.
     아이콘은 Tabler 한 세트에서만 가져와요 (frontend/icons.js). */
  .icon-btn { width: 30px; height: 30px; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center;
    border-radius: 6px; cursor: pointer; user-select: none;
    color: #fff; background: var(--text-primary); transition: background 0.12s; }
  .icon-btn:hover { background: var(--point); }
  .icon-btn .icon { display: block; }

  /* 검색칸 줄: [추가 버튼] [검색칸] 을 한 줄에 놓아요 */
  /* 채팅 좌측의 1:1·그룹 탭은 아래 여백을 두지 않아요 (2026-09-17 원장 지적).
     공통 .tabs 는 본문과 거리를 두려고 margin-bottom: 28px 를 갖는데, 목록 칸에서는
     그 28px 위에 검색줄 여백 12px 이 더해져 40px 이 됐어요.
     학원 관리는 탭이 없어 검색줄이 맨 위에 바로 오니, 같은 간격이 되도록 0 으로 둬요.
     (인라인 스타일로 덮지 않고 여기 규칙으로 둬요 — 다음에 또 헷갈리지 않게요) */
  /* 탭 글자가 오른쪽 칸 첫 줄과 같은 높이에 오게 탭 자체 여백(8px)만큼 끌어올려요.
     아래 여백은 **공통 .tabs 와 같은 28px** 을 그대로 써요 — 예전엔 0 으로 눌러놨는데,
     그때는 검색줄에 위 여백(12px)이 있어서였어요. 지금은 위 여백이 칸(.list-panel)으로
     옮겨가서 0 으로 두면 탭과 검색칸이 딱 붙어버려요 (원장 지적 2026-09-26). */
  .list-panel > .tabs { margin-top: -8px; }

  /* ── 목록의 할 일 버튼 — '학생 추가' · '공지 작성' (원장 지정 2026-10-12 · 앱의 '계획하기' 와 같은 모양) ──
     목록 **맨 아래**, 왼쪽에 글자만큼의 흰 바탕 · 검은 1px 테두리 박스. 예전 검색칸 왼쪽 검은 '+' 네모를 대신해요.
     목록이 짧으면 마지막 줄 바로 아래, 길면 목록이 스크롤되고 버튼은 그 아래에 있어요. */
  .add-row { padding: 14px var(--pad-x) 18px; flex-shrink: 0; }
  .add-btn { display: inline-flex; align-items: center; height: 32px; padding: 0 14px; border: 1px solid var(--text-primary); border-radius: 6px;
    background: #fff; color: var(--text-primary); font-size: 12px; font-weight: 600; cursor: pointer; user-select: none; transition: color 0.12s, border-color 0.12s; }
  .add-btn:hover { color: #e53e3e; border-color: #e53e3e; }   /* 주 버튼 hover 는 붉은색 (가이드 3번) */
  .student-list:has(+ .add-row) { flex: 0 1 auto; }
  .list-search.with-add { display: flex; align-items: center; gap: 10px; }
  .list-search.with-add .search-input { flex: 1; min-width: 0; }

  .student-list { flex: 1; overflow-y: auto; scrollbar-width: none; }
  .student-list::-webkit-scrollbar { display: none; }
  .student-item { display: flex; align-items: center; gap: 10px; padding: 13px var(--pad-x); cursor: pointer; transition: background 0.1s; border-radius: 6px; }
  .student-item:hover { background: #fafafa; }
  .student-item.active { background: #f5f5f5; }
  .student-avatar { width: 28px; height: 28px; border-radius: 50%; background: #f0f0f0; display: flex; align-items: center; justify-content: center; font-size: 11px; color: var(--text-muted); flex-shrink: 0; }
  .student-name { font-size: 12px; font-weight: 500; margin-bottom: 2px; }
  .student-meta { font-size: 11px; color: var(--text-muted); }
  /* 개인정보 동의 안 한 학생 (2026-10-07). 동의 전에는 앱이 아예 안 열려요 —
     학원이 그 사실을 모르면 "앱이 고장났다" 는 연락만 받게 돼요.
     색은 새로 고르지 않고 이미 쓰는 '주의' 색(지각 표·학부모 표)을 그대로 써요 */
  .consent-no { color: #d97706; }
  .consent-warn { font-size: 11.5px; color: #d97706; background: #fffbeb; padding: 9px 12px; margin-bottom: 8px; }
  /* 질문 AI 풀이 (2026-10-10) — 박스 없이 위아래 0.5px 선으로 대화와 나눠요. 학생 답과 다를 때만 위의 주황 경고 (동의 안내와 같은 모양) */
  .ai-solve { margin: 6px 0 22px; padding: 16px 0; border-top: 0.5px solid var(--line); border-bottom: 0.5px solid var(--line); }
  .ai-solve-warn { font-size: 13px; padding: 11px 14px; margin-bottom: 14px; border-radius: 6px; }
  .ai-solve-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
  .ai-solve-meta { font-size: 11.5px; color: var(--text-muted); }
  .ai-solve-label { font-size: 11.5px; color: var(--text-muted); margin: 12px 0 4px; }
  .ai-solve-text { font-size: 13px; line-height: 1.75; color: var(--text-primary); white-space: pre-wrap; }
  .ai-solve-text.muted { color: var(--text-secondary); }
  .ai-solve-answers { font-size: 13px; font-weight: 600; color: var(--text-primary); margin-top: 12px; font-variant-numeric: tabular-nums; }
  .ai-solve-note { font-size: 12px; color: var(--text-secondary); margin-top: 12px; white-space: pre-wrap; }
  .ai-solve-wait { font-size: 12.5px; color: var(--text-muted); padding: 4px 0; }
  #cActions .busy { opacity: 0.5; pointer-events: none; }

  /* 상세 패널 */
  .detail-panel { flex: 1; overflow-y: auto; padding: var(--pad-top) var(--pad-x); scrollbar-width: none; position: relative; }
  .detail-panel::-webkit-scrollbar { display: none; }

  .panel-title { font-size: 14px; font-weight: 600; letter-spacing: -0.3px; margin-bottom: 7px; }
  .panel-sub { font-size: 11px; color: var(--text-muted); margin-bottom: 32px; }

  /* 탭 */
  /* 첫 탭도 좌우 여백을 똑같이 가져야 글자가 밑줄 한가운데 놓여요.
     예전엔 .tab:first-child 의 padding-left 를 0 으로 없애서 본문 왼쪽 끝에
     맞췄는데, 그러면 첫 탭만 글자가 밑줄 안에서 왼쪽으로 쏠려 보였어요.
     대신 **줄 전체를 왼쪽 여백만큼 당겨서** 맞춰요 — 여백은 그대로 두고
     위치만 옮기는 거라 글자가 계속 가운데에 있어요. */
  .tabs { display: flex; margin-bottom: 28px; margin-left: -16px; }
  .tab { font-size: 11px; color: var(--text-muted); padding: 8px 16px; cursor: pointer; border-bottom: 1.5px solid transparent; margin-bottom: -0.5px; transition: color 0.12s, border-color 0.12s; user-select: none; }
  .tab:hover { color: var(--text-primary); }
  .tab.active { color: var(--text-primary); font-weight: 500; border-bottom-color: var(--text-primary); }
  /* 사이드바 메뉴 하나 안에서 화면을 오가는 탭 (제목 줄 바로 아래, 전체 폭).
     본문 안의 .tabs 와 달리 왼쪽 목록 위까지 덮어야 해서 body-wrap 위에 놓아요.
     탭은 "고르기"가 아니라 "화면 전환"이라 배경 박스가 아니라 밑줄이에요 (가이드 4번). */
  /* flex-wrap 이 있어야 항목이 많을 때 줄이 넘어가요. 상담 예약의 월 칩을 8개에서
     12개(1~12월)로 늘리면서 좁은 왼쪽 칸에서 삐져나갔어요 (2026-09-17).
     항목이 적은 화면(질문 게시판 과목·성적 회차)은 줄이 안 넘어가니 영향이 없어요. */
  /* 탭 글자가 --pad-x 줄에 놓이게, 줄 여백에서 탭 자체 여백(16px)을 빼요 */
  .section-tabs { display: flex; flex-wrap: wrap; padding: 0 calc(var(--pad-x) - 16px); flex-shrink: 0; }
  /* 월 탭(1~12월)은 한 줄에 다 들어가야 해요 (2026-09-17 원장 기준).
     기본 탭 여백(16px)이면 13칸에 700px 이 필요해서 화면 절반을 먹어요.
     이 줄에서만 여백을 좁혀 420px 안에 들어가게 해요. */
  .section-tabs.month-tabs .tab { padding: 8px 7px; }
  /* 줄 여백 16px + 탭 자체 여백 16px = 32px 라 본문 왼쪽 끝과 맞아요.
     (.tabs 의 -16px 당김은 여기 필요 없어요 — 줄 자체가 전체 폭이라서요) */
  .section-tabs .tab { margin-bottom: -0.5px; }

  .tab-panel { display: none; }
  .tab-panel.active { display: block; }

  /* 폼 */
  /* ── 입력 칸 (가이드 2번·14번 5항) ──
     칸은 "글이 들어갈 만큼"만 차지해요. 예전에는 한 줄에 칸이 하나면
     밑줄이 화면 끝까지(950px 쯤) 늘어졌어요 — 이름 세 글자 적는 칸이
     화면을 가로지르면 여백이 아니라 빈 껍데기로 보여요.
     그래서 칸마다 최대 너비를 두고, 남는 자리는 여백으로 둬요.
     패널 자체의 너비는 예전처럼 제한하지 않아요. (2026-09-05 변경) */
  .form-row { display: flex; gap: 24px; margin-bottom: 18px; flex-wrap: wrap; }
  .form-field { flex: 1 1 180px; max-width: 290px; }
  /* 상한을 두면 안 되는 칸이 세 가지 있어요. 화면마다 클래스를 새로 달지 않게
     :has() 로 알아서 잡아요.

       1) 긴 글을 쓰거나 읽는 칸 — 340px 안에서 줄바꿈되면 읽기 어려워요
       2) 고르는 칩이 늘어선 줄 — 좁히면 칩이 여러 줄로 접혀서 한눈에 안 들어와요
       3) 표를 담은 줄 — 표는 스스로 필요한 만큼 써야 해요 */
  .form-field:has(.field-textarea) { max-width: 620px; }
  .form-field:has(.field-value.long) { max-width: 620px; }
  .form-field:has(.type-options) { max-width: none; }
  .form-field:has(table) { max-width: none; }
  /* 제목처럼 중간 길이인 칸은 손으로 지정해요 */
  .form-field.wide { max-width: 470px; }
  /* 칸 안에 고르는 칩이 있어도 폭을 늘리지 않아요 (2026-09-17).
     :has(.type-options) 규칙이 max-width 를 없애는데, 그러면 옆 칸이 오른쪽으로
     밀려서 위아래 줄의 시작점이 어긋나요 (선생님 상세의 '역할' 과 '상태'). */
  .form-field.fixed-width:has(.type-options) { max-width: 290px; }
  /* 칸 위에 붙는 라벨.
     "여기에 무엇이 들어가는지" 를 알려주는 글자라, 구역 제목(.section-title)과
     **같은 위계**로 본다는 게 이 프로젝트의 결정이에요 (2026-09-05).
     그래서 크기·두께·색을 제목과 똑같이 맞춰요. 둘의 모양이 갈라지면
     "청구할 항목 고르기" 와 "청구서 이름" 이 다른 급으로 보여요. */
  .field-label { font-size: 12px; font-weight: 500; color: var(--point); letter-spacing: 0.2px; margin-bottom: 6px; }
  .field-value { font-size: 12px; color: var(--text-primary); border-bottom: 0.5px solid var(--line); padding-bottom: 6px; }
  .field-input { width: 100%; font-size: 12px; font-family: inherit; color: var(--text-primary); border: none; border-bottom: 0.5px solid var(--line); outline: none; padding-bottom: 6px; min-height: 22px; caret-color: var(--text-primary); background: transparent; transition: border-color 0.15s; }
  .field-input:focus { border-bottom-color: var(--text-primary); }
  .field-input:empty::before { content: attr(data-placeholder); color: #d0d0d0; }
  .field-input:focus::before { content: ''; }

  .divider { height: 0; margin: 22px 0; }
  /* 화면 안의 작은 구역 제목 ("다가오는 상담", "양식 내려받기" 등).
     10px 회색이라 잘 안 보인다는 피드백으로 12px + 포인트 컬러로 바꿨어요 (2026-09-05). */
  /* 구역 제목은 그 아래 필드 라벨보다 한 단계 위 위계예요 — 더 크고 굵고 진하게(대문자·포인트색 아님).
     위계: panel-title(14) > section-title(13, 검정 볼드) > field-label(12, 포인트색 대문자) */
  /* 좌우 2단을 풀면 줄이 화면 끝(1150px)까지 늘어져서 가운데가 텅 비어 보여요.
     입력칸을 290px 로 묶는 것과 같은 이유로, 한 칸짜리 화면의 본문 폭을 묶어요. */
  .one-col { max-width: 880px; }
  /* 오른쪽 칸 (미리 보기 · 통계) — 왼쪽보다 좁게, 위아래로 쌓여요 */
  .col-split > .col.col-right { flex: 0 0 420px; }
  /* 기록 탭의 오른쪽 칸은 왼쪽과 줄을 맞춰요 — '통계' 제목이 왼쪽 '월 탭' 줄에,
     첫 숫자가 왼쪽 첫 invoice 줄에 오도록 (원장 지적 2026-09-24).
     선택자를 길게 쓴 이유: 위의 `.tabs ~ .tab-panel > .col-split > .col { padding-top: 18px }`
     가 더 구체적이라 짧게 쓰면 밀려요. 72 = 그 18 + 검색칸 줄 높이 54. */
  .col-split > .col.col-right.hist-right { padding-top: 72px; }
  .col-right.hist-right > .section-title { margin-bottom: 26px; }
  .col-right .summary { display: block; }
  .col-right .sumstats { flex-direction: column; gap: 0; row-gap: 0; }
  .col-right .sumstats > div { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 9px 0; }
  .col-right .sumstats b { font-size: 16px; margin-right: 0; order: 2; }
  .col-right .sumstats .u { order: 1; }

  /* invoice 목록 줄의 발행일 (2026-09-24 원장 요청) */
  .inv-date { font-size: 11px; color: var(--text-muted); flex-shrink: 0; margin-right: 4px; }
  /* 줄을 눌러 펼친 칸 — 항목과 결제 이력만 */
  .inv-open { padding: 2px 0 16px; }
  .inv-open-row { display: flex; justify-content: space-between; gap: 16px; font-size: 11.5px; color: var(--text-secondary); padding: 4px 0; }

  /* ── invoice 미리 보기 ("고급 브랜드가 보내는 청구서처럼", 원장 지정 2026-09-24) ──
     이 한 장만 **박스**예요. 실제로 종이 한 장이 어떻게 생겼는지 보여주는 것이라
     경계가 있어야 "이게 한 장" 이라고 읽혀요 (가이드 0-1 예외 — 좌석 격자와 같은 부류).
     색은 새로 만들지 않았어요: 검정·회색·초록(감면)뿐이에요. */
  .inv-paper {
    background: #fff; border: 1px solid #e6e6e6; border-radius: 4px;
    padding: 36px 34px 28px; box-sizing: border-box;
  }
  .inv-brand { font-size: 15px; font-weight: 700; letter-spacing: -0.2px; color: var(--text-primary); }

  .inv-meta { display: flex; gap: 30px; margin: 30px 0 22px; flex-wrap: wrap; }
  .inv-meta > div { display: flex; flex-direction: column; gap: 5px; }
  .inv-meta span { font-size: 10px; color: var(--text-muted); letter-spacing: 0.4px; }
  .inv-meta b { font-size: 12.5px; font-weight: 600; color: var(--text-primary); }
  .inv-title { font-size: 12.5px; color: var(--text-secondary); margin-bottom: 14px; }

  /* 항목 줄 — 여기는 금액 표라서 가는 선을 둬요 (선을 없앤 규칙의 예외) */
  .inv-lines { border-top: 1px solid var(--text-primary); }
  .inv-line { display: flex; justify-content: space-between; gap: 20px; padding: 11px 0; border-bottom: 0.5px solid #ececec; }
  .inv-line-name { font-size: 12.5px; color: var(--text-primary); }
  .inv-line-amount { font-size: 12.5px; color: var(--text-primary); font-variant-numeric: tabular-nums; }
  /* 깎인 줄 — 초록(가이드 1번의 '긍정' 색) */
  .inv-line-off .inv-line-name, .inv-line-off .inv-line-amount { color: #16a34a; font-size: 11.5px; }

  .inv-sum { padding: 14px 0 0; }
  .inv-sum > div { display: flex; justify-content: space-between; gap: 20px; padding: 4px 0; }
  .inv-sum span { font-size: 11.5px; color: var(--text-muted); }
  .inv-sum b { font-size: 12.5px; font-weight: 500; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
  .inv-sum-off span, .inv-sum-off b { color: #16a34a; }

  .inv-total { display: flex; align-items: baseline; justify-content: space-between; padding: 14px 0 0; margin-top: 10px; border-top: 1px solid var(--text-primary); }
  .inv-total span { font-size: 11px; color: var(--text-muted); letter-spacing: 0.4px; }
  .inv-total b { font-size: 22px; font-weight: 700; letter-spacing: -0.5px; font-variant-numeric: tabular-nums; }
  .inv-total b small { font-size: 12px; font-weight: 500; margin-left: 3px; }

  .inv-foot { font-size: 10.5px; color: var(--text-muted); margin-top: 26px; line-height: 1.6; }

  /* 탭 안의 탭 (invoice 의 발행·항목).
     **.tabs 를 쓰지 않아요** — 공통 switchTab 이 '.tabs .tab' 을 전부 비활성으로 만들어서
     바깥 탭을 오가면 안쪽 탭이 통째로 사라져요 (2026-09-24에 겪음). 모양은 .tabs 와 같아요. */
  .subtabs { display: flex; margin-bottom: 22px; margin-left: -16px; }
  .subtabs .tab { margin-bottom: 0; }
  /* 탭 안의 탭 (invoice 의 발행·항목) — 고르지 않은 쪽은 숨겨요 */
  .sub-panel { display: none; }
  .sub-panel.active { display: block; }
  /* 줄 전체를 눌러 펴는 줄 ('자세히' 버튼을 없애고 줄을 누르게 했어요 — 원장 지정 2026-09-23) */
  .linked-item.row-open { cursor: pointer; border-radius: 6px; }
  .linked-item.row-open:hover { background: #fafafa; }

  /* 제목 줄 오른쪽 끝에 버튼 하나 — "목록 + 새로 만들기" 를 한 화면에 펼치지 않고
     버튼으로 넘어가는 화면에서 써요 (2026-09-23 원장 지정) */
  .head-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
  .head-row .section-title { margin-bottom: 0; }

  .section-title { font-size: 13px; font-weight: 600; color: var(--text-primary); letter-spacing: -0.1px; text-transform: none; margin-bottom: 14px; }

  /* 출결 기록 */
  .attend-row { display: flex; align-items: center; gap: 12px; padding: 11px 0; }
  .attend-date { font-size: 12px; color: var(--text-muted); width: 80px; }
  .attend-detail { font-size: 12px; color: var(--text-secondary); flex: 1; }
  .attend-pen { margin-top: 3px; color: #C8323B; }
  .attend-pen .linked-action { margin-left: 6px; }
  .attend-pen.is-off { color: var(--text-secondary); }
  .attend-badge { font-size: 10px; padding: 2px 8px; border-radius: 20px; font-weight: 500; }
  .badge-in { color: #16a34a; background: #f0fdf4; }
  .badge-late { color: #d97706; background: #fffbeb; }
  .badge-absent { color: #e53e3e; background: #fff5f5; }
  /* 중립 (예정·취소처럼 좋지도 나쁘지도 않은 상태) — 가이드 11번 회색 */
  .badge-neutral { color: var(--text-muted); background: #f0f0f0; }
  /* 정보 (처리 중처럼 "지금 돌아가고 있다" 는 상태) — 가이드 11번 파랑 */
  .badge-waiting { color: #2563eb; background: #eff6ff; }

  /* 상담 분류. 색은 가이드 11번 팔레트를 그대로 쓰고,
     어느 분류에 어느 색을 줄지는 상담 스펙(docs/decisions/consultation.md 6번)을 따라요. */
  .cat-learning { color: #2563eb; background: #eff6ff; }
  .cat-admission { color: #7c3aed; background: #f5f3ff; }
  .cat-other { color: var(--text-muted); background: #f0f0f0; }
  .cat-parent { color: #d97706; background: #fffbeb; }
  /* 등원 상담은 아직 등록 안 된 외부인 건이라 눈에 띄게 붉은색으로 (2026-09-11 원장) */
  .cat-enrollment { color: #e53e3e; background: #fff5f5; }

  /* ── 테두리형 배지 ──
     채운 배지(분류·유형)와 구별하려고 상태 배지는 테두리로 그려요.
     같은 색이어도 "채움 vs 테두리" 로 달라 보여요 — 학부모 상담(주황 채움)과
     지난 일정(주황 테두리), 처리 중(파랑 테두리)과 새 글(파랑 채움)이 안 헷갈려요.
     색상 클래스(badge-waiting 등)와 함께 써서 글자색이 곧 테두리색이 돼요. */
  .badge-line { background: transparent; border: 1px solid currentColor; }
  /* 목록 맨 오른쪽 시간 태그 (질문 게시판). 회색 테두리. */
  .time-badge { font-size: 11px; color: var(--text-secondary); border: 1px solid #d5d5d5; border-radius: 20px; padding: 1px 8px; white-space: nowrap; flex-shrink: 0; }

  /* 성적 */
  .score-row { display: flex; align-items: center; gap: 12px; padding: 11px 0; }
  .score-subject { font-size: 12px; color: var(--text-primary); flex: 1; }
  .score-val { font-size: 12px; font-weight: 500; }
  .score-grade { font-size: 11px; color: var(--text-muted); }

  /* 액션 */
  .action-row { display: flex; gap: 20px; align-items: center; margin-top: 24px; }
  /* 주 버튼은 이미 검정 강조예요. hover 에 opacity 를 주면 회색처럼 흐려져
     '약해지는' 느낌이라, 탭·보조 버튼(회색->검정)과 방향이 반대였어요.
     그래서 흐리지 않고 그대로 검정을 유지해요 (2026-09-12). */
  /* ── 1급 버튼 (docs/decisions/SOLIST_TOSS_DESIGN_GUIDE.md 1부, 2026-09-17) ──
     "지금 이 화면에서 눌러야 할 행동" 하나만 배경을 채워요. 미니멀이 지나쳐서 실행
     버튼과 그냥 글자가 구분되지 않던 문제를 풀려고 넣었어요.
     [중요] 단위는 **보이는 폼(탭·패널) 하나당 1개** 예요 (원장 결정) — 탭을 바꾸면 보이는
       폼이 달라지니, 그 순간 화면에 1급은 하나만 보여요.
     가이드 0-3 "버튼에 배경색 없음" 의 명시적 예외이고, 예외는 이 클래스 하나뿐이에요.
     새 색을 만들지 않아요 — 배경은 기존 --text-primary 를 그대로 써요.
     우리 버튼은 <span> 이라 :disabled 가 걸리지 않아서 그 규칙은 두지 않아요.
     2급(검은 글자)은 기존 .btn-primary, 3급(회색)은 기존 .btn-secondary 가 그대로 맡아요. */
  .btn-1st { font-size: 12px; display: inline-flex; align-items: center; gap: 4px; padding: 9px 18px; background: var(--text-primary); color: #fff; font-weight: 600; border-radius: 6px; cursor: pointer; user-select: none; transition: opacity 0.15s; }
  /* hover 는 흐려지는 게 아니라 **포인트 컬러로 바뀌어요** (2026-09-17 원장 요청).
     dim 은 "약해지는" 느낌이라 눌리는 신호로 읽히지 않았어요.
     가이드 1번은 포인트 컬러(--point)를 섹션 제목 전용으로 뒀는데, 여기 한 곳이 예외예요 —
     화면당 하나뿐인 1급 버튼이라 "여기저기 칠하는" 상태가 되지 않아요. */
  .btn-1st:hover { background: var(--point); }
  .btn-1st:active { background: var(--point); opacity: 0.85; }

  /* ── 2급 버튼 (흰 배경 + 검은 테두리) ──
     1급(채운 버튼) 옆에 서면 맨 글자 버튼이 위계가 안 맞아 보였어요 (2026-09-17 원장 지적).
     서식 항목(.rich-label)과 같은 "흰 배경 + 검은 테두리" 를 써요.
     높이는 1급과 맞아요 — 1급은 패딩 9, 여기는 패딩 8 + 테두리 1 이라 같은 줄에서 나란해요.
     가이드 0-3 의 두 번째 예외예요 (첫 번째는 .btn-1st). */
  .btn-2nd { display: inline-flex; align-items: center; gap: 4px; padding: 8px 16px; font-size: 12px; font-weight: 500; color: var(--text-primary); background: transparent; border: 1px solid var(--text-primary); border-radius: 6px; cursor: pointer; user-select: none; transition: background 0.12s, color 0.12s, border-color 0.12s; }
  .btn-2nd:hover { color: var(--point); border-color: var(--point); }
  .btn-2nd:active { background: var(--sidebar-active); }

  .btn-primary { font-size: 12px; font-weight: 600; cursor: pointer; user-select: none; transition: color 0.12s; }
  /* 주 버튼(저장·수정 계열)은 원래 검정. hover 시 붉은색으로 반응해요.
     (보조 버튼의 회색→검정 위계는 그대로 두고, 검정 버튼만 붉게 강조) */
  .btn-primary:hover { color: #e53e3e; }
  /* 같은 줄에 나란히 놓이니 크기를 맞춰요 (전부 12px).
     위계는 굵기와 색으로만 구분해요 — 크기까지 다르면 정렬이 어긋나 보여요. */
  .btn-secondary { font-size: 12px; color: var(--text-muted); cursor: pointer; user-select: none; transition: color 0.12s; }
  .btn-secondary:hover { color: var(--text-primary); }
  /* 삭제 계열은 항상 또렷한 빨강이에요 (가이드 0번 원칙 7).
     예전엔 opacity 0.6 으로 흐리게 뒀는데, 빨강으로 안 읽혀서 삭제인 줄 몰랐어요.
     눈에 덜 띄게 하려고 흐리게 하지 말고, 위치로 분리하세요. */
  /* 상태에 따라 색(위험/보통)이 바뀌는 버튼도 위치는 오른쪽 끝에 고정해요 */
  .action-right { margin-left: auto; }

  .btn-danger { font-size: 12px; color: #e53e3e; cursor: pointer; user-select: none; margin-left: auto; transition: opacity 0.15s; }
  .btn-danger:hover { opacity: 0.55; }
  /* 다른 버튼 없이 혼자 있을 때는 맨 오른쪽으로 밀리지 않게 해요 */
  .action-row .btn-danger:only-child { margin-left: 0; }

  /* 제목 줄에 액션을 함께 두는 머리 (공지 삭제처럼 본문이 길어도 항상 보여야 하는 것) */
  .panel-head { display: flex; align-items: flex-start; gap: 16px; margin-bottom: 4px; }
  .panel-head .panel-title { margin-bottom: 7px; }
  .panel-head .spacer { flex: 1; }

  /* 학부모 연결 */
  .linked-item { display: flex; align-items: center; gap: 10px; padding: 12px 0; }
  .linked-name { font-size: 12px; font-weight: 500; flex: 1; }
  .linked-phone { font-size: 11px; color: var(--text-muted); }
  /* 목록 줄 안의 삭제·빼기. 가이드 0-6 대로 빨강이에요.
     (예전엔 회색이라 삭제인 줄 몰랐어요) */
  .linked-remove { font-size: 11px; color: #e53e3e; cursor: pointer; user-select: none; transition: opacity 0.15s; }
  .linked-remove:hover { opacity: 0.55; }

  /* 목록 줄 안의 삭제가 아닌 부가 동작 (링크 보기 등) */
  .linked-action { font-size: 11px; color: var(--text-muted); cursor: pointer; user-select: none; transition: color 0.12s; }
  .linked-action:hover { color: var(--text-primary); }

  /* 좁은 자리(칩·목록 줄)에서 쓰는 삭제 × 표시.
     가이드 0-6 대로 또렷한 빨강이고, inline-flex 라서 글자 기준선에 처지지 않고
     항상 세로 가운데에 놓여요. (예전엔 baseline 에 붙어서 아래로 치우쳐 보였어요) */
  .remove-x { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; font-size: 14px; line-height: 1; color: #e53e3e; cursor: pointer; user-select: none; flex-shrink: 0; transition: opacity 0.15s; }
  .remove-x:hover { opacity: 0.55; }
  /* Library 자료 한 줄 (원장 지정 2026-10-20): 이름 · 용량 · 설명 · 올린 사람을 한 줄에, 끝에 '이동' · ×.
     '이동' 글자와 × 는 같은 16px 높이 칸에 가운데 — 전에는 글자 줄 높이가 달라 위아래가 어긋났어요 */
  .shelf-item .shelf-item-name { flex: 0 1 auto; min-width: 0; max-width: 45%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .shelf-item .shelf-item-meta { flex: 1 1 0; min-width: 0; margin-top: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .shelf-item .shelf-item-act { display: inline-flex; align-items: center; height: 16px; line-height: 1; flex-shrink: 0; }

  /* ══════════════════════════════════════
     공지사항 피드 (Threads 톤)
     docs/decisions/SOLIST_NOTICE_FEED_DESIGN.md 를 그대로 옮긴 거예요.

     이 화면만 다르게 쓰는 값이 딱 두 개예요 — 본문 크기(13px)와 줄간격(1.7).
     다른 화면은 정보를 빽빽하게 담는 톤이지만, 피드는 읽는 화면이라
     줄간격이 넉넉해야 글 덩어리가 안 답답해요.
     색·글꼴·버튼은 나머지 화면과 완전히 같아요.
     ══════════════════════════════════════ */

  /* 피드는 읽는 화면이라 한 줄이 너무 길면 눈이 다음 줄을 못 찾아요.
     그래서 여기는 폭을 제한해요 (가이드 14-5 의 "패널은 전체 폭" 예외). */
  .feed { max-width: 640px; }
  /* 질문 게시판은 이미 좌우 2분할이라 오른쪽 대화 칸이 좁아요.
     여기서 다시 640px 로 묶으면 오른쪽에 빈 여백이 크게 남아, 칸을 꽉 채워요. */
  #chatPanel .feed { max-width: none; }
  #chatPanel .thread-input .form-field:has(.field-textarea) { max-width: none; }

  /* ── 공지사항 2분할 ──
     왼쪽은 전체 공지(시간순), 오른쪽은 중요 공지만. body-wrap 이 flex 예요. */
  .notice-main { flex: 1; overflow-y: auto; padding: 28px 32px; min-width: 0; }
  .notice-important { width: 320px; flex-shrink: 0; overflow-y: auto; padding: 28px 24px 28px 36px; }
  /* 공지 · 피드 한 화면 (원장 지정 2026-10-20): 위 [공지][피드] 1차 탭 + 2차 필터 → 이름 · 설명 → 좁은 목록 | 본문 (작성 중엔 오른쪽 서식 칸) */
  .board-intro { padding: 20px var(--pad-x) 4px; flex-shrink: 0; }
  .board-intro .panel-sub { margin-bottom: 0; }
  .notice-board > .detail-panel { flex: 1 1 0; min-width: 0; }
  /* 오른쪽 중요 공지는 좁으니 한 줄씩 압축해서 보여줘요 */
  .imp-item { padding: 14px 0; cursor: pointer; }
  .imp-title { font-size: 13px; font-weight: 600; color: var(--text-primary); line-height: 1.4; }
  .imp-meta { font-size: 11px; color: var(--text-muted); margin-top: 3px; }
  .imp-body { font-size: 12px; color: var(--text-secondary); line-height: 1.6; margin-top: 4px;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
  /* 중요 공지 표시 배지 (왼쪽 피드의 중요 글에 붙여요) */
  .badge-important { font-size: 10px; padding: 2px 8px; border-radius: 20px; font-weight: 600; color: #e53e3e; background: #fff5f5; }

  /* 채팅 안 읽음 수 — 카카오톡 '1' 처럼 붉은 숫자 */
  .chat-unread { font-size: 10px; font-weight: 700; color: #fff; background: #e53e3e; border-radius: 10px; padding: 1px 6px; min-width: 16px; text-align: center; flex-shrink: 0; }
  .chat-read { font-size: 10px; color: #e53e3e; margin-top: 4px; display: flex; align-items: center; gap: 4px; }

  .feed-post { display: flex; gap: 12px; padding: 22px 0; }

  /* 아바타 — 항상 왼쪽 고정 열. 이름 첫 글자만 넣어요 (사진 업로드는 없어요) */
  .feed-post-avatar { width: 36px; height: 36px; border-radius: 50%; background: #f0f0f0; display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 500; color: var(--text-muted); flex-shrink: 0; }

  /* min-width:0 이 없으면 긴 글이 flex 칸을 밀어내서 가로 스크롤이 생겨요 */
  .feed-post-body { flex: 1; min-width: 0; }

  .feed-post-header { display: flex; align-items: baseline; gap: 6px; margin-bottom: 4px; }
  .feed-post-author { font-size: 12px; font-weight: 600; color: var(--text-primary); }
  .feed-post-role { font-size: 10px; color: var(--text-muted); }
  .feed-post-time { font-size: 10px; color: var(--text-muted); margin-left: auto; }

  .feed-post-title { font-size: 13px; font-weight: 600; color: var(--text-primary); margin-bottom: 6px; line-height: 1.4; }

  .feed-post-content { font-size: 13px; color: var(--text-secondary); line-height: 1.7; white-space: pre-wrap; word-break: break-word; }
  /* 길면 네 줄에서 자르고 "더보기" 로 펼쳐요 */
  .feed-post-content.truncated { display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
  .feed-post-more { display: block; font-size: 12px; color: var(--text-muted); cursor: pointer; margin-top: 4px; user-select: none; transition: color 0.12s; }
  .feed-post-more:hover { color: var(--text-primary); }

  /* 이미지 그리드 — 최대 4장, 개수별 배치 */
  /* 사진 미리보기 (SNS PC 처럼 크게). 사진이라 둥근 모서리는 허용 (디자인 문서). */
  .feed-post-images { display: grid; gap: 3px; margin-top: 10px; }
  .feed-post-images img { width: 100%; display: block; cursor: zoom-in; border-radius: 6px; background: #fafafa; }

  /* 한 장: 자르지 않고 원본 비율 그대로 크게 보여줘요 (세로 최대 520px).
     예전엔 object-fit:cover + height:100% 라 높이가 무너지거나 잘려 보였어요. */
  .feed-post-images.grid-1 { max-width: 540px; }
  .feed-post-images.grid-1 img { height: auto; max-height: 520px; object-fit: contain; }

  /* 여러 장: 정사각형으로 채워 잘라요 (그리드가 고르게 보이게) */
  .feed-post-images.grid-2 { grid-template-columns: 1fr 1fr; max-width: 540px; }
  .feed-post-images.grid-3 { grid-template-columns: 1.2fr 1fr; grid-template-rows: 1fr 1fr; max-width: 540px; }
  .feed-post-images.grid-4 { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; max-width: 540px; }
  .feed-post-images.grid-2 img,
  .feed-post-images.grid-4 img { aspect-ratio: 1 / 1; height: 100%; object-fit: cover; }
  .feed-post-images.grid-3 img { height: 100%; object-fit: cover; }
  .feed-post-images.grid-many { grid-template-columns: 1fr 1fr 1fr; max-width: 540px; }
  .feed-post-images.grid-many img { aspect-ratio: 1 / 1; height: 100%; object-fit: cover; }
  .feed-post-images.grid-3 img:first-child { grid-row: 1 / 3; aspect-ratio: 3 / 4; }
  .feed-post-images.grid-3 img:not(:first-child) { aspect-ratio: 4 / 3; }

  /* 이미지가 아닌 파일 — 그림으로 안 펼치고 목록으로만 */
  .feed-post-files { margin-top: 8px; }
  .feed-post-file { font-size: 11px; color: var(--text-muted); padding: 8px 0; cursor: pointer; transition: color 0.12s; }
  .feed-post-file:hover { color: var(--text-primary); }

  .feed-post-footer { display: flex; align-items: center; gap: 14px; margin-top: 10px; }
  .feed-post-target { font-size: 10px; color: var(--text-muted); padding: 2px 8px; background: #f0f0f0; border-radius: 10px; }
  .feed-post-reaction { font-size: 12px; color: var(--text-muted); cursor: pointer; user-select: none; transition: color 0.12s; }
  .feed-post-reaction:hover { color: var(--text-primary); }
  /* 눌렀을 때만 색이 들어가요. 평소엔 무채색이에요 */
  .feed-post-reaction[data-active="true"] { color: #e53e3e; }

  /* 글 고치기·지우기는 오른쪽 끝에 조용히 둬요 (가이드 0-7: 지우기는 줄 안의 ×) */
  .feed-post-actions { margin-left: auto; display: flex; align-items: center; gap: 10px; }

  /* 더 불러오기 / 끝 */
  .feed-end { font-size: 11px; color: var(--text-muted); text-align: center; padding: 18px 0; }
  .feed-more-btn { font-size: 12px; color: var(--text-muted); cursor: pointer; user-select: none; text-align: center; padding: 16px 0; transition: color 0.12s; }
  .feed-more-btn:hover { color: var(--text-primary); }

  /* ══════════════════════════════════════
     채팅 DM (인스타그램 스타일)
     주의: 가이드 0-1(박스 금지)의 예외예요. 채팅 말풍선은 이 화면에만 써요.
     내 말은 오른쪽, 상대 말은 왼쪽. 연속 메시지는 묶어서 아바타·이름을 한 번만.
     (2026-09-11 원장 요청) ══════════════════════════════════════ */
  .dm { display: flex; flex-direction: column; gap: 2px; padding: 4px 2px; }
  .dm-row { display: flex; align-items: flex-end; gap: 8px; margin-top: 2px; }
  .dm-row.mine { flex-direction: row-reverse; }
  /* 보낸 사람이 바뀌면 위에 간격을 더 줘서 덩어리로 보여요 */
  .dm-row.first { margin-top: 12px; }

  .dm-avatar { width: 28px; height: 28px; border-radius: 50%; background: #eaeaea; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center; font-size: 11px; color: var(--text-secondary); }
  /* 아바타 자리를 늘 비워둬서 묶인 메시지가 나란히 정렬돼요 */
  .dm-avatar.hidden { visibility: hidden; }

  .dm-stack { display: flex; flex-direction: column; max-width: min(66%, 460px); min-width: 0; }
  .dm-row.mine .dm-stack { align-items: flex-end; }

  /* 그룹 방에서 상대 이름 (덩어리 첫 줄에만) */
  .dm-name { font-size: 11px; color: var(--text-muted); margin: 0 4px 3px; }

  .dm-line { display: flex; align-items: flex-end; gap: 6px; }
  .dm-row.mine .dm-line { flex-direction: row-reverse; }

  .dm-bubble { padding: 8px 12px; border-radius: 16px; font-size: 13.5px; line-height: 1.5;
    white-space: pre-wrap; word-break: break-word; }
  /* 상대 말: 옅은 회색 / 내 말: 포인트 색 옅게 */
  .dm-row.them .dm-bubble { background: #f0f0f0; color: var(--text-primary); border-bottom-left-radius: 4px; }
  .dm-row.mine .dm-bubble { background: #e7eef0; color: var(--text-primary); border-bottom-right-radius: 4px; }

  /* 시간 · 안읽음 — 말풍선 옆에 작게 */
  .dm-meta { font-size: 10px; color: var(--text-muted); white-space: nowrap; padding-bottom: 1px; }
  .dm-unread { font-size: 10px; font-weight: 700; color: #e53e3e; white-space: nowrap; padding-bottom: 1px; }

  /* 사진·파일은 말풍선 없이 바로 (인스타처럼 사진은 둥근 썸네일) */
  .dm-bubble.media { padding: 0; background: none !important; }
  .dm-media img { max-width: 240px; border-radius: 14px; display: block; cursor: zoom-in; }
  .dm-file { font-size: 12px; color: var(--text-secondary); background: #f0f0f0; border-radius: 12px;
    padding: 8px 12px; cursor: pointer; }

  /* ── 채팅 화면 레이아웃 ──
     detail-panel 을 꽉 채워서 입력칸을 항상 맨 아래 고정해요.
     내용 폭은 760px 로 제한하고 가운데 둬요 — 오른쪽 여백이 뜨거나
     divider 가 너무 길어지는 걸 막아요. */
  /* 대화 + 오른쪽 정보 패널을 나란히 */
  .chat-stage { display: flex; height: 100%; }
  /* chatView 안을 [대화 | 메모] 2열로. 그 오른쪽에 정보 패널이 와요. */
  #chatView { flex: 1; display: flex; min-width: 0; }
  .chat-convo { flex: 2 1 0; min-width: 300px; display: flex; flex-direction: column; padding: 20px 24px; }
  /* 대화와 정보 패널 사이 공간을 채우는 메모 (2026-09-11 원장 아이디어) */
  .chat-memo { flex: 1 1 0; min-width: 220px; padding: 20px 20px 20px 32px; display: flex; flex-direction: column; }
  .chat-memo-status { font-size: 10px; color: var(--text-muted); font-weight: 400; letter-spacing: 0; text-transform: none; }
  .chat-memo-note { font-size: 11px; color: var(--text-muted); margin-bottom: 10px; }
  /* 메모 입력칸: 남는 세로를 다 쓰고, 밑줄이 아니라 옅은 상자로 (계속 보는 곳이라) */
  .chat-memo-box { flex: 1; border: none !important; background: #fafafa; border-radius: 8px; padding: 12px !important;
    overflow-y: auto; line-height: 1.6; font-size: 13px; }
  .chat-memo-box:focus { background: #f5f5f5; }

  /* 오른쪽 참여자·자료 패널. 좁은 화면에선 접을 수 있어요(정보 버튼). */
  .chat-info { width: 280px; flex-shrink: 0; overflow-y: auto; padding: 24px 20px 24px 32px; }
  .info-member { display: flex; align-items: center; gap: 8px; padding: 7px 0; }
  .info-member .dm-avatar { width: 26px; height: 26px; }
  .info-member .nm { font-size: 12px; }
  .info-member .rl { font-size: 11px; color: var(--text-muted); margin-left: auto; }
  .info-images { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 4px; }
  .info-images img { width: 100%; aspect-ratio: 1/1; object-fit: cover; border-radius: 6px; cursor: zoom-in; background: #fafafa; }
  .info-file { font-size: 11px; color: var(--text-secondary); padding: 8px 0; cursor: pointer; }
  .info-file:hover { color: var(--text-primary); }
  .chat-head { display: flex; align-items: center; gap: 6px; padding-bottom: 18px; flex-shrink: 0; }
  /* 대화만 스크롤. 헤더·입력칸은 고정돼요 */
  .dm-scroll { flex: 1; overflow-y: auto; padding: 8px 0; scrollbar-width: none; }
  .dm-scroll::-webkit-scrollbar { display: none; }

  /* 헤더 아이콘 (검색·메모·참여자·초대). 전부 같은 크기·간격. */
  .chat-icon { color: var(--text-muted); cursor: pointer; display: inline-flex; align-items: center;
    width: 24px; height: 24px; justify-content: center; border-radius: 6px; transition: color 0.12s, background 0.12s; flex-shrink: 0; }
  .chat-icon:hover { color: var(--text-primary); background: var(--sidebar-hover); }
  .chat-icon.on { color: var(--point); background: var(--sidebar-active); }
  /* 메모·정보 켜고 끄기는 아이콘이 아니라 글자예요 (2026-09-17 원장 요청 — 이모지·아이콘이
     다른 메뉴와 톤이 안 맞았어요, 가이드 0-2). 고른 상태는 다른 화면과 같은 회색 배경
     박스로 표시해요 (가이드 0-5). 여백은 아이콘용 정사각이 아니라 글자에 맞춰요. */
  .chat-toggle { font-size: 11px; color: var(--text-muted); cursor: pointer; user-select: none; padding: 5px 10px; border-radius: 5px; transition: background 0.12s, color 0.12s; }
  .chat-toggle:hover { color: var(--text-primary); background: var(--sidebar-hover); }
  .chat-toggle.on { color: var(--text-primary); background: var(--sidebar-active); font-weight: 500; }
  /* '추가'(그룹에 사람 넣기)는 실행 버튼이라 검은 배경이지만, 옆의 '메모'·'정보' 와
     **같은 크기** 여야 해요 (2026-09-17 원장 지적 — 1급 버튼 크기라 혼자 컸어요). */
  .chat-toggle.add { color: #fff; background: var(--text-primary); font-weight: 500; }
  .chat-toggle.add:hover { color: #fff; background: var(--point); }
  .chat-search-bar { display: flex; align-items: center; gap: 12px; padding: 10px 0 6px; }
  .chat-search-bar .search-input { flex: 1; }

  /* 그룹 초대에서 고른 사람 칩 */
  .picked-chip { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-primary);
    background: var(--sidebar-active); border-radius: 14px; padding: 4px 10px; margin: 0 6px 6px 0; }
  .picked-remove { color: var(--text-muted); cursor: pointer; font-size: 13px; line-height: 1; }
  .picked-remove:hover { color: #e53e3e; }

  /* 입력칸: 검은 테두리로 또렷하게, 하단 고정 */
  .chat-input { flex-shrink: 0; padding-top: 10px; }
  /* 한 줄로 유지해요 (2026-09-17 원장 지적 — 두 줄처럼 보였어요).
     원인: align-items:flex-end + 28px 원형 버튼이라 줄 높이가 버튼 기준으로 늘어났어요.
     버튼을 24px 로 줄이고 가운데 정렬로 바꿔서 입력칸(22px) 한 줄에 맞췄어요. */
  .chat-input-bar { display: flex; align-items: center; gap: 8px;
    border: 1px solid var(--text-primary); border-radius: 12px; padding: 6px 10px; }
  .chat-textarea { flex: 1; min-height: 22px; max-height: 120px; overflow-y: auto; border: none !important; padding: 4px 2px; }
  /* 입력줄의 기호 버튼 (2026-09-17 원장 요청) — + 는 파일 붙이기, ↑ 는 보내기.
     글자 버튼 둘("파일" "보내기")이 나란히 서면 정작 입력칸보다 눈에 띄었어요.
     이모지가 아니라 글자 기호라 가이드 0-2 에 맞아요. 동그란 모양은 입력줄 안에서만 써요. */
  .chat-send-btn { width: 24px; height: 24px; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center;
    font-size: 13px; line-height: 1; border-radius: 50%; cursor: pointer; user-select: none;
    color: var(--text-secondary); border: 1px solid var(--line); background: transparent; transition: background 0.12s, color 0.12s, border-color 0.12s; }
  .chat-send-btn:hover { color: var(--text-primary); border-color: var(--text-secondary); }
  .chat-send-btn.primary { color: #fff; background: var(--text-primary); border-color: var(--text-primary); font-weight: 600; }
  .chat-send-btn.primary:hover { background: var(--point); border-color: var(--point); }
  .chat-textarea:focus { border: none !important; }
  /* 검색에 안 걸린 메시지는 숨겨요 */
  .dm-row.nomatch { display: none; }



    /* 질문 게시판: 대화 입력줄.
     박스로 감싸지 않고 위쪽 0.5px 선으로만 본문과 나눠요 (가이드 0-1). */
  .thread-input { padding-top: 6px; margin-top: 26px; }
  .thread-input-row { display: flex; align-items: flex-end; gap: 20px; }
  /* 답을 적는 칸은 기본 1줄이에요 (2026-09-17 원장 요청 — 3줄이라 글자와 밑줄 사이가 멀어 보였어요).
     채팅 입력칸(.chat-textarea)과 같은 22px 로 맞췄어요. 길게 쓰면 알아서 늘어나요.
     예전 규칙은 .thread-input-row 를 가리켰는데 그 클래스를 쓰는 화면이 없어서 아무 효과가 없었어요. */
  /* 쓸 수 없는 상태(맡지 않았거나 완료됨)일 때 이유를 적어두는 자리 */
  .thread-locked { font-size: 11px; color: var(--text-muted); padding: 14px 0 0; line-height: 1.6; }

  /* 미리보기 (작성 폼에서 고른 이미지) */
  /* 공지·피드 목록의 대표 이미지 (작게, 오른쪽) */
  .notice-thumb { width: 40px; height: 40px; border-radius: 6px; object-fit: cover; flex-shrink: 0; margin-left: 10px; background: var(--sidebar-active); }
  .upload-preview { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
  .upload-preview-item { position: relative; width: 64px; height: 64px; border-radius: 4px; overflow: hidden; }
  .upload-preview-item img { width: 100%; height: 100%; object-fit: cover; display: block; }
  /* 대표 이미지 고르기 (공지·피드) — 사진 아래쪽 띠. 고른 사진은 검은 띠 '대표' */
  .upload-preview-item.is-cover { outline: 2px solid var(--text-primary); outline-offset: -2px; }
  .upload-preview-cover { position: absolute; left: 0; right: 0; bottom: 0; text-align: center; font-size: 10px; line-height: 16px; color: #fff; background: rgba(0,0,0,0.45); cursor: pointer; user-select: none; }
  .upload-preview-item.is-cover .upload-preview-cover { background: var(--text-primary); font-weight: 600; }
  .upload-preview-remove { position: absolute; top: 2px; right: 2px; width: 16px; height: 16px; display: inline-flex; align-items: center; justify-content: center; font-size: 12px; line-height: 1; color: #fff; background: rgba(0,0,0,0.5); border-radius: 50%; cursor: pointer; user-select: none; }

  /* 피커 */
  .picker-field { position: relative; }
  .picker-input { cursor: pointer; display: flex; align-items: center; min-height: 22px; padding-bottom: 6px; border-bottom: 0.5px solid var(--line); transition: border-color 0.15s; user-select: none; font-size: 12px; color: #d0d0d0; }
  .picker-input.has-value { color: var(--text-primary); }
  .picker-input.open { border-bottom-color: var(--text-primary); }
  .picker-list { position: absolute; top: 100%; left: 0; right: 0; z-index: 100; background: #fff; padding-top: 4px; }
  /* 목록에서 하나를 고르는 것도 선택이에요. 고른 항목에 배경 박스를 깔아요 (가이드 8번). */
  .picker-option { padding: 9px 10px; border-radius: 6px; font-size: 12px; color: var(--text-secondary); cursor: pointer; transition: background 0.12s, color 0.12s; user-select: none; }
  .picker-option:hover { background: var(--sidebar-hover); color: var(--text-primary); }
  .picker-option.selected { background: var(--sidebar-active); color: var(--text-primary); font-weight: 500; }

  /* 빈 상태 */
  .empty { padding: 60px 0; text-align: center; color: var(--text-muted); }
  .empty-title { font-size: 12px; color: var(--text-secondary); margin-bottom: 4px; }
  /* 선생님마다 AI 사용량 (원장만 · 2026-10-10) — 선생님 화면의 빈 자리에. 성적 표(.gtable)와 같은 모양 */
  .ai-usage { text-align: left; margin: -40px 0 48px; }
  .ai-usage:empty { display: none; }
  .ai-usage-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 10px; }
  .ai-usage-month { font-size: 12px; color: var(--text-secondary); font-variant-numeric: tabular-nums; display: inline-flex; gap: 10px; align-items: center; }
  .ai-usage-nav { cursor: pointer; padding: 0 4px; color: var(--text-primary); user-select: none; }
  .ai-usage-table { width: 100%; font-size: 12px; font-variant-numeric: tabular-nums; }
  .ai-usage-table td.name-cell { text-align: left; }
  .ai-usage-table th.name-cell { text-align: left; }
  /* 보낸 것을 **전부** 고치지 않고 보냈으면 굵게 — 색으로 겁주지 않아요 (빨강은 지우기 전용) */
  .ai-usage-table td.ai-usage-flag { font-weight: 700; color: var(--text-primary); }
  .ai-usage-note { margin-top: 8px; }

  /* 성공 */
  .success-msg { font-size: 11px; color: #38a169; margin-top: 16px; opacity: 0; transition: opacity 0.2s; height: 16px; }
  .success-msg.show { opacity: 1; }
  .field-value.editable[contenteditable="true"] { outline: none; border-bottom-color: var(--text-primary); }
  .field-value.editable { transition: border-color 0.15s; }
  .success-msg.show { opacity: 1; }

  /* LOGIN — 구글 로그인처럼 (원장 지정 2026-10-24 · 사진 없음 · 앱과 같은 구성)
     연한 회색 바탕 위 둥근 흰 카드 · 왼쪽 이름 · '로그인' · 안내 / 오른쪽 테두리 칸 · 아래 오른쪽 둥근 버튼.
     760px 이하는 카드 없이 흰 화면에 위아래로. 색은 구글 파랑 대신 Solist 포인트(검정) */
  .login-overlay { position: fixed; inset: 0; background: #fff; /* PC · 태블릿도 흰 바탕 (원장 지정 2026-10-24) */ z-index: 100; display: flex; overflow-y: auto; }
  .login-main { flex: 1; display: flex; align-items: center; justify-content: center; padding: 40px 24px; box-sizing: border-box; }
  .login-card { width: 100%; max-width: 880px; background: #fff; border-radius: 16px; padding: 40px 40px 32px; box-sizing: border-box;
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 40px; row-gap: 28px; }
  .login-logo { font-size: 20px; font-weight: 800; letter-spacing: -0.4px; color: var(--text-primary); }
  .login-sub { font-size: 14px; color: var(--text-secondary); margin-top: 14px; line-height: 1.5; }
  .login-right { padding-top: 6px; }
  /* 테두리 칸 + 칸 이름 (구글 outlined) — 이름은 적기 시작하면 테두리 위로 (모션 가이드 25번) */
  .gfield { position: relative; display: block; margin-bottom: 18px; }
  .gfield input { width: 100%; box-sizing: border-box; height: 56px; padding: 0 16px; font-size: 16px; font-family: inherit; color: var(--text-primary);
    background: #fff; border: 1px solid #8a8a93; border-radius: 6px; outline: none; }
  .gfield input:focus { border: 2px solid var(--text-primary); padding: 0 15px; }
  .gfield span { position: absolute; left: 12px; top: 28px; padding: 0 4px; background: #fff; font-size: 16px; color: #6b6b74; pointer-events: none;
    transform: translateY(-50%); transform-origin: left center; transition: top 0.3s cubic-bezier(0.33, 1, 0.68, 1), transform 0.3s cubic-bezier(0.33, 1, 0.68, 1), color 0.3s; }
  .gfield input:focus + span, .gfield input:not(:placeholder-shown) + span { top: 0; transform: translateY(-50%) scale(0.72); }
  .gfield input:focus + span { color: var(--text-primary); font-weight: 600; }
  .login-overlay.bad .gfield input { border-color: #C8323B; }
  .login-overlay.bad .gfield span { color: #C8323B; }
  /* 자리를 미리 비워둬요 — 오류가 뜰 때 버튼이 아래로 밀리면 누르려던 자리가 달라져요 */
  .login-error { font-size: 12.5px; color: #C8323B; min-height: 18px; margin: -6px 0 6px; line-height: 1.4; }
  .login-help { font-size: 13px; color: var(--text-secondary); line-height: 1.5; }
  .login-actions { grid-column: 1 / -1; display: flex; justify-content: flex-end; }
  /* 상자 없는 '로그인 →' — 글자와 오른쪽 화살표만 (원장 지정 2026-10-24) */
  .login-next { display: inline-flex; align-items: center; gap: 6px; height: 40px; padding: 0 2px 0 8px; color: var(--text-primary);
    font-size: 15px; font-weight: 700; cursor: pointer; user-select: none; transition: opacity 0.12s; }
  .login-next svg { display: block; }
  .login-next:hover { opacity: 0.6; }
  .login-next:focus-visible { outline: 2px solid var(--text-primary); outline-offset: 2px; }
  /* 초대로 가입하는 화면(solist-invite)은 예전 모양 그대로 (가운데 칸 · 밑줄 입력) */
  .login-box { width: 300px; }
  .login-box .login-logo { font-size: 24px; margin-bottom: 30px; }
  .login-field { margin-bottom: 20px; }
  .login-label { font-size: 12px; font-weight: 500; color: var(--point); letter-spacing: 0.2px; margin-bottom: 7px; }
  .login-input { width: 100%; font-size: 13px; font-family: inherit; color: var(--text-primary); border: none; border-bottom: 0.5px solid var(--line); outline: none; padding-bottom: 9px; background: transparent; transition: border-color 0.15s; }
  .login-input:focus { border-bottom-color: var(--text-primary); }
  /* 초대로 가입하는 화면(solist-invite)은 아직 큰 버튼을 써요 */
  .login-btn { width: 100%; justify-content: center; padding: 12px 18px; font-size: 13px; }
  @media (max-width: 760px) {
    .login-overlay { background: #fff; }
    .login-main { align-items: center; padding: 32px 8px; }
    .login-card { grid-template-columns: minmax(0, 1fr); padding: 0 16px; border-radius: 0; row-gap: 26px; }
  }
  @media (prefers-reduced-motion: reduce) { .gfield span { transition: none; } }

  .form-note { font-size: 10px; color: var(--text-muted); margin-top: 14px; line-height: 1.5; }

  /* 입력 칸 바로 아래에 붙는 경고. 어느 칸이 잘못됐는지 그 자리에서 알려줘요.
     (화면 아래쪽 success-msg 는 저장 결과용이라, 칸이 여러 개면 어디가 문제인지 알 수 없어요) */
  .field-error { font-size: 10px; color: #e53e3e; margin-top: 5px; line-height: 1.4; min-height: 13px; }
  /* 값이 잘못된 입력 칸은 밑줄도 빨강으로 바꿔요 */
  .field-input.invalid { border-bottom-color: #e53e3e; }
  .list-empty { font-size: 12px; color: var(--text-muted); padding: 14px var(--pad-x); }

  /* ── 가이드 5번: 여러 줄 입력 ── */
  /* 여러 줄 글 칸. **1줄로 시작해서 쓰는 만큼 늘어나요** (2026-09-26).
     예전 기본값이 58px(3줄)이라 빈 칸인데 밑줄이 저 아래 있었고, 화면마다 22px 로 덮어쓰고 있었어요
     (채팅 · 학습 스케줄). 기본을 1줄로 바꾸고 그 덮어쓰기들을 지웠어요 —
     같은 것을 여러 곳에서 고치면 반드시 한 곳이 빠져요. */
  .field-textarea { width: 100%; font-size: 12px; font-family: inherit; color: var(--text-primary); border: none; border-bottom: 0.5px solid var(--line); outline: none; padding-bottom: 6px; min-height: 22px; background: transparent; caret-color: var(--text-primary); line-height: 1.65; transition: border-color 0.15s; }
  .field-textarea:focus { border-bottom-color: var(--text-primary); }
  .field-textarea:empty::before { content: attr(data-placeholder); color: #d0d0d0; }
  .field-textarea:focus::before { content: ''; }

  /* ── 체크박스 (가이드 10번) ──
     브라우저 기본 체크박스는 운영체제 강조색(맥이면 주황)이 나와서 우리 톤과 안 맞아요
     (2026-09-17 원장 지적). 가이드 10번이 정한 모양으로 직접 그려요 —
     14px 사각(모서리 3px), 고르면 검정(--text-primary) 배경 + 흰 체크.
     화면 9곳이 기본 체크박스를 쓰고 있어서, HTML 을 건드리지 않고 여기서 한 번에 맞춰요. */
  input[type="checkbox"] {
    appearance: none; -webkit-appearance: none;
    width: 14px; height: 14px; border-radius: 3px;
    /* 글자와 세로 가운데를 맞춰요 (2026-09-17 원장 지적 — 살짝 위로 떠 보였어요).
       appearance:none 을 준 칸은 기준선(baseline)에 붙어서 글자보다 높이 올라가요.
       줄이 label 안에 있어 부모의 align-items:center 가 닿지 않아요. */
    vertical-align: middle;
    border: 1px solid #d0d0d0; background: #fff;
    flex-shrink: 0; cursor: pointer; position: relative;
    transition: background 0.15s, border-color 0.15s;
  }
  input[type="checkbox"]:hover { border-color: var(--text-secondary); }
  input[type="checkbox"]:checked { background: var(--text-primary); border-color: var(--text-primary); }
  /* 체크 표시는 CSS 로 그려요 (가이드 0-2 — 이모지·아이콘 대신) */
  input[type="checkbox"]:checked::after {
    content: ''; position: absolute; left: 3.5px; top: 1px;
    width: 4px; height: 7px;
    border: solid #fff; border-width: 0 1.5px 1.5px 0;
    transform: rotate(45deg);
  }

  /* ── 가이드 8번: 선택 UX 는 배경 박스 방식 ──
     "같은 계열 항목 중 하나를 고르는" UI 는 사이드바 메뉴와 같은 방식으로 표시해요.
     선택된 항목에 옅은 회색 배경(--sidebar-active)을 깔고 모서리를 둥글게 해요.
     예전에는 opacity 로 흐리게 하는 dim 방식이었는데, 어느 게 선택됐는지 잘 안 보였어요.
     탭(화면 전환)은 이 방식이 아니라 밑줄 방식(가이드 4번)을 써요. */
  .type-options { display: flex; gap: 6px; flex-wrap: wrap; }
  /* 고르는 칩. 선택하면 회색 배경 박스 — 박스는 글자를 살짝 감싸는 크기로 둬요.
     (2026-09-15 원장 요청으로 8px 14px · 6px 에서 줄임 — 크면 박스가 튀어서 절제된 톤과 안 맞아요) */
  .type-option { display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px; border-radius: 5px; font-size: 12px; color: var(--sidebar-text); cursor: pointer; user-select: none; transition: background 0.12s, color 0.12s; }
  .type-option:hover { background: var(--sidebar-hover); color: var(--text-primary); }
  .type-option.active { background: var(--sidebar-active); color: var(--text-primary); font-weight: 500; }

  /* ── 출석부: 좌석 배치 ──
     주의: 여기는 SOLIST_DESIGN_GUIDE.md 0번 원칙 1(박스 금지)의 **명시적 예외**예요.
     ibex_attendance.html 원본의 색채움 칩 방식을 그대로 가져왔어요.

     이유: 좌석 수십 개를 한눈에 스캔해야 하는 밀도 높은 격자라,
     텍스트 색만으로는 "지금 누가 나가 있는지"가 즉시 안 보여요.
     이 예외는 좌석 그리드에만 해당해요 — 좌석을 눌렀을 때 열리는 편집 패널,
     외출 일정 탭, 나머지 모든 화면은 표준 원칙(박스 없음)을 그대로 따라요. */

  /* 원본 팔레트 (ibex_attendance.html) */
  .seating-board { --seat-alert: #e5484d; --seat-amber: #C77D0F; --seat-teal: #0F4C5C; --seat-sel: rgba(0,0,0,0.035); --seat-dim: 0.5; --seat-sub: #6e6e6e; }

  /* 좌석 현황: 왼쪽 배치도(넓게) + 오른쪽 좌석 편집 패널.
     align-items:stretch 라 오른쪽 패널이 배치도 높이만큼 늘어나 세로 구분선이 끝까지 이어져요. */
  .board-layout { display: flex; align-items: stretch; }
  .board-main { flex: 1; min-width: 0; }
  .board-side { width: 680px; flex-shrink: 0; margin-left: 40px; padding-left: 0; }

  /* 방을 세로로 쌓아요 (교실이 위아래로 나열) */
  .rooms { display: flex; flex-direction: column; gap: 36px; align-items: flex-start; }
  .room .rtitle { font-size: 14px; font-weight: 600; margin-bottom: 10px; letter-spacing: -0.01em; }
  .room .rtitle .rcount { font-size: 11px; font-weight: 400; color: var(--seat-sub); margin-left: 4px; }
  .room .rtitle .rdel { font-size: 11px; color: var(--seat-sub); cursor: pointer; margin-left: 10px; font-weight: 400; }
  .room .rtitle .rdel:hover { color: var(--seat-alert); }

  .grid { display: grid; gap: 5px; }
  /* 정상 착석(담임 있음·외출 아님)은 테두리만 있는 흰 칸이에요. 상태가 있을 때만 배경색을 채워요. */
  .seat { padding: 7px 9px; min-height: 46px; cursor: pointer; border: 1px solid #cfcfcf; border-radius: 3px; transition: background .15s; position: relative; }
  .seat:hover { background: var(--seat-sel); }
  /* 배경색으로 상태를 나타내는 칸은 테두리를 지워요 (색이 곧 표시라서요) */
  .seat.out-now, .seat.out-amber, .seat.noteacher, .seat.not-arrived { border-color: transparent; }
  /* 이상 없는 학생(담임 있음·외출 아님·착석)은 테두리를 검정으로 (기본 회색 → 검정) */
  .seat.normal { border-color: var(--text-primary); }
  /* 1열: 이름(왼쪽) + 자리 번호(오른쪽) 를 한 줄에 둬요 (2026-09-17 원장 요청).
     예전엔 이름·학교·번호가 세 줄이라 칩이 길었어요. 번호는 '번' 없이 숫자만이에요. */
  .seat .row1 { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
  .seat .nm { font-size: 13px; font-weight: 500; letter-spacing: -0.02em; line-height: 1.25; min-width: 0; }
  /* 이름 줄과 학교 사이를 넓게 띄워요 (2026-09-17 원장 요청 — 2px 이라 붙어 보였어요) */
  .seat .sc { font-size: 11px; color: var(--seat-sub); margin-top: 7px; line-height: 1.2; }
  /* 자리 번호: 이름과 같은 줄 오른쪽 끝, 이름과 같은 크기 (2026-09-11 → 2026-09-17 1열로 옮김).
     예전엔 오른쪽 위에 아주 작게(9.5px) 박혀 있어서 잘 안 보였어요. */
  .seat .no { text-align: right; font-size: 13px; color: var(--seat-sub); line-height: 1.25; flex-shrink: 0; font-variant-numeric: tabular-nums; }
  .seat .cap { font-size: 10.5px; color: var(--seat-alert); margin-top: 2px; line-height: 1.2; }

  .seat.empty { opacity: var(--seat-dim); }
  .seat.empty .nm { color: var(--seat-sub); font-weight: 400; }
  .seat.empty .nm::before { content: '+ '; }
  .seat.special { opacity: .4; }
  .seat.special .nm { font-weight: 400; color: var(--seat-sub); }

  /* 정기 외출 = 빨강 */
  .seat.out-now { background: var(--seat-alert); }
  .seat.out-now .nm { color: #fff; font-weight: 600; }
  .seat.out-now .sc { color: rgba(255,255,255,0.85); }
  .seat.out-now .no { color: rgba(255,255,255,0.85); opacity: 1; }
  .seat.out-now .cap { color: rgba(255,255,255,0.9); }
  .seat.out-now:hover { background: #d43b40; }

  /* 비정기 외출 = 앰버 */
  .seat.out-amber { background: var(--seat-amber); }
  .seat.out-amber .nm { color: #fff; font-weight: 600; }
  .seat.out-amber .sc { color: rgba(255,255,255,0.85); }
  .seat.out-amber .no { color: rgba(255,255,255,0.85); opacity: 1; }
  .seat.out-amber .cap { color: rgba(255,255,255,0.9); }
  .seat.out-amber:hover { background: #a9680b; }

  /* 미등원(오늘 등원 기록 없음) = 회색 (2026-09-17 원장 요청 — 정기·비정기 외출과 같은 위계).
     외출(빨강·앰버)과 헷갈리지 않게 회색 계열로 둬요. 추록의 미등원 규칙과도 같은 방향이에요.
     키오스크를 쓰지 않아 오늘 등원 기록이 한 건도 없으면 이 표시를 아예 켜지 않아요. */
  .seat.not-arrived { background: #9a9a9a; }
  .seat.not-arrived .nm { color: #fff; font-weight: 600; }
  .seat.not-arrived .sc { color: rgba(255,255,255,0.85); }
  .seat.not-arrived .no { color: rgba(255,255,255,0.85); opacity: 1; }
  .seat.not-arrived .cap { color: rgba(255,255,255,0.9); }
  .seat.not-arrived:hover { background: #8a8a8a; }

  /* 담임 필요 = 틸 */
  .seat.noteacher { background: var(--seat-teal); }
  .seat.noteacher .nm { color: #fff; font-weight: 600; }
  .seat.noteacher .sc { color: rgba(255,255,255,0.82); }
  .seat.noteacher .no { color: rgba(255,255,255,0.82); opacity: 1; }
  .seat.noteacher:hover { background: #0c3d49; }

  /* 좌석을 고르면 그 좌석만 남기고 나머지를 흐리게 해요.
     예전처럼 고른 좌석에 옅은 배경을 덮으면, 빨강·앰버·틸 색이 지워져서
     "지금 무슨 상태였는지"를 알 수 없게 돼요. 색은 그대로 두고 주변만 비켜줘요. */
  /* 좌석을 고르면 나머지 칸이 연해져요 (원장 요청 — 고른 자리에 눈이 가게).
     정도는 0.12 -> 0.35 (2026-09-17 원장 선택). 0.12 는 너무 옅어서 주변 칸이
     무슨 색이었는지 알 수 없었어요.
     ("모든 학생이 회색으로 변한다" 던 문제는 이 흐림이 아니라 **미등원 회색**이
      전원에게 붙어서였어요 — 4-1 절 참고. 흐림은 원장 요청대로 유지해요.) */
  .rooms.focused .seat { opacity: 0.35; }
  .rooms.focused .room .rtitle { opacity: 0.5; }
  /* 고른 좌석의 테두리는 그 좌석 색을 따라가요.
     색이 없는 좌석(담임도 있고 외출도 아닌 정상 상태)만 검은 테두리예요. */
  /* 고른 칸은 또렷하게 남겨요. 테두리는 두르지 않아요 (2026-09-17 원장 요청) —
     정상 좌석은 이미 검은 테두리가 있어서 이중으로 보였어요.
     주변이 연해지는 것만으로 어느 칸을 골랐는지 충분히 보여요. */
  .rooms.focused .seat.sel { opacity: 1; }
  .seat.addseat { opacity: .5; border-color: transparent; outline: 0.5px dashed var(--line); display: flex; align-items: center; justify-content: center; }
  .seat.addseat .nm { color: var(--seat-teal); font-weight: 600; font-size: 12px; }
  .seat.addseat:hover { opacity: 1; background: transparent; }
  .addroom { align-self: flex-start; padding: 40px 20px; display: flex; align-items: center; }

  /* 상단 요약 통계바 */
  .summary { display: flex; align-items: center; gap: 26px; margin-bottom: 26px; font-size: 13px; }
  /* 지표가 6개로 늘면서 좁은 칸에서는 줄이 넘어가야 해요 (2026-09-17 결제 화면) */
  .summary .sumstats { display: flex; flex-wrap: wrap; gap: 26px; row-gap: 10px; }
  .summary b { font-weight: 600; font-size: 15px; margin-right: 5px; letter-spacing: -0.01em; }
  .summary .u { color: var(--seat-sub); }
  .summary .sumlegend { margin-left: auto; display: flex; flex-wrap: wrap; gap: 8px; font-size: 12px; }
  /* 범례 한 칸 = 그 색으로 채운 칩.
     예전엔 6px 점이었는데 파랑과 보라, 주황과 빨강이 그 크기에서는 구분이 안 됐어요
     (원장 지적 2026-09-23 — "점을 키우는 것 말고 다른 방법으로").
     점을 없애고 **줄 전체에 색을 칠했어요.** 색이 칠해지는 면적이 20배쯤 넓어지고,
     화면 안(좌석·달력 칸)에 칠해진 색과 같은 색이라 범례로 바로 읽혀요.
     색 묶음은 어느 것도 새로 만들지 않았어요 — 가이드 1번의 5색 그대로예요. */
  .summary .lg { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 6px; }
  .summary .lg b { font-size: 12px; font-weight: 700; color: inherit; margin-right: 0; }
  .summary .lg .dot { display: none; }
  .summary .lg:has(.dot.red) { background: #fff5f5; color: #e53e3e; }
  .summary .lg:has(.dot.amber) { background: #fffbeb; color: #d97706; }
  .summary .lg:has(.dot.teal) { background: #e9f0f2; color: var(--point); }
  /* 미등원 = 회색 (2026-09-17). 좌석 칩의 .not-arrived 배경과 같은 색이어야 범례가 맞아요 */
  .summary .lg:has(.dot.gray) { background: #f0f0f0; color: #6e6e6e; }

  /* ── 상담 예약: 달력 (2026-09-23 원장 지정) ──
     좌석 그리드와 같은 부류예요 — 한 달을 한눈에 훑어야 하는 밀도 높은 격자라
     "박스 금지" 원칙의 예외를 그대로 적용해요 (가이드 0-1의 격자 예외).
     칸 자체는 테두리 없이 **가는 선 격자**로만 나누고, 색을 채우는 건 상담 한 줄뿐이에요. */
  .cal-layout .board-side { width: 460px; }
  /* 날짜를 열면 오른쪽 칸이 460px 를 다 가져가서 달력이 300px 로 눌렸어요 — 월 탭이 '1/월' 로 쪼개지고
     요일이 두 줄이 됐어요 (2026-10-19 사용 점검 B-10 · 1440 · 1280). 달력은 420px 를 지키고 오른쪽 칸이 320px 까지 줄어요.
     그래도 모자라면 오른쪽 칸이 달력 아래로 내려가요 */
  .cal-layout { flex-wrap: wrap; column-gap: 40px; row-gap: 40px; }
  .cal-layout .board-main { flex: 1 1 420px; min-width: min(420px, 100%); }
  .cal-layout .board-side { width: auto; flex: 1 1 320px; max-width: 460px; min-width: 0; margin-left: 0; }
  /* 월 탭 — 출석부 탭줄(.tabs)과 같은 부품이라 아래 여백(28px)도 같아요.
     1~12월이 한 줄에 들어가게 탭 여백만 좁히고, 그만큼 줄을 왼쪽으로 당겨
     '1월' 글자가 본문 왼쪽 끝과 맞아요 (원장 지적 2026-09-23: 1월 왼쪽에 빈 자리가 있었어요). */
  .tabs.month-tabs { margin-left: -7px; }
  .tabs.month-tabs .tab { padding: 8px 7px; }
  /* 칸을 선으로 나누지 않아요 — 출석부 좌석처럼 **틈**으로만 나눠요 (원장 지정: "테두리는 아예 없게") */
  .cal-head, .cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
  /* 요일은 가운데, 풀네임으로 (원장 지정). 색은 또렷하게 — 검정, 일요일만 빨강 (원장 지적: 너무 연했어요) */
  .cal-dow { font-size: 11.5px; color: var(--text-primary); padding: 0 0 10px; letter-spacing: 0.2px; text-align: center; }
  .cal-dow.sun { color: #e53e3e; }
  .cal-cell {
    min-height: 104px; padding: 7px 9px; cursor: pointer; border-radius: 7px;
    border: 1px solid transparent;   /* 평소엔 안 보여요. 오늘 칸만 검게 나타나요 */
    transition: background 0.12s, opacity 0.12s; overflow: hidden;
  }
  .cal-cell:hover { background: #fafafa; }
  /* 그 달에 없는 날 (1일 앞·마지막 주 뒤) — 아무것도 없어요 */
  .cal-cell.blank { cursor: default; }
  .cal-cell.blank:hover { background: transparent; }
  /* 오늘 칸만 검은 테두리 (원장 지정). 좌석에서 '정상' 칸을 검은 테두리로 두는 것과 같은 방식이에요 */
  .cal-cell.today { border-color: var(--text-primary); }
  /* 날짜는 칸 오른쪽 위 (원장 지정) */
  .cal-date { font-size: 12px; color: var(--text-secondary); text-align: right; margin-bottom: 5px; }
  .cal-cell.today .cal-date { color: var(--text-primary); font-weight: 600; }
  .cal-items { display: flex; flex-direction: column; gap: 3px; }
  .cal-item {
    font-size: 10.5px; line-height: 1.5; padding: 2px 5px; border-radius: 4px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  /* 취소된 상담은 줄을 그어요 — 지운 게 아니라 취소라서 자리는 남겨둬요 */
  .cal-item.off { text-decoration: line-through; opacity: 0.55; }
  /* 완료 — 앞에 작은 체크 아이콘 (원장 지정 2026-10-24 · 예정과 똑같아 보였어요). 취소는 가로줄 그대로 */
  .cal-done { display: inline-flex; vertical-align: -1px; margin-right: 3px; }
  .cal-key { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 10px; font-size: 11px; color: var(--text-secondary); }
  .cal-key-item { display: inline-flex; align-items: center; gap: 4px; }
  .day-item.off .day-time, .day-item.off .day-who { text-decoration: line-through; opacity: 0.6; }
  /* 고른 칸만 또렷하고 나머지는 흐려요 (좌석과 같은 방식 — 테두리를 두르지 않아요) */
  .cal.focused .cal-cell { opacity: 0.4; }
  .cal.focused .cal-cell.sel { opacity: 1; background: var(--sidebar-active); }

  /* 이 달 상담을 종류별로 세는 줄 — 출석부 요약줄과 같은 부품(.summary)이에요.
     점 색은 달력 칸의 분류 색과 같아요. 색이 다르면 범례가 아니게 돼요. */
  /* 상담 분류 — 달력 칸에 칠해지는 색(.cat-*)과 **같은 값**이어야 범례가 맞아요 */
  .summary .lg:has(.dot.c-learning) { background: #eff6ff; color: #2563eb; }
  .summary .lg:has(.dot.c-admission) { background: #f5f3ff; color: #7c3aed; }
  .summary .lg:has(.dot.c-parent) { background: #fffbeb; color: #d97706; }
  .summary .lg:has(.dot.c-enrollment) { background: #fff5f5; color: #e53e3e; }
  .summary .lg:has(.dot.c-other) { background: #f0f0f0; color: #6e6e6e; }

  /* 오른쪽 칸: 그날 상담 줄 */
  .day-item { display: flex; align-items: center; gap: 10px; padding: 12px 8px; cursor: pointer; border-radius: 5px; }
  .day-item:hover { background: #fafafa; }
  .day-item.active { background: var(--sidebar-active); }
  .day-time { font-size: 12px; color: var(--text-secondary); flex-shrink: 0; }
  .day-who { font-size: 12.5px; color: var(--text-primary); margin-right: auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* ── 출석부: 순회 체크 (2026-09-26) ── */
  /* 시각 칩. 아침 8시~밤 12시면 33개까지 늘어나서 줄이 넘어가게 둬요 */
  .round-times { display: flex; flex-wrap: wrap; gap: 6px; }
  .round-time {
    display: inline-flex; align-items: center; gap: 5px; padding: 6px 10px;
    background: var(--sidebar-active); border-radius: 5px; font-size: 12px;
    font-variant-numeric: tabular-nums; color: var(--text-primary);
  }
  .round-chip-n { font-size: 10px; color: var(--text-muted); margin-left: 3px; }

  /* 오늘 순회 — 교실마다 한 줄, 라운드마다 칩 하나 */
  .round-room { margin-bottom: 20px; }
  .round-room-name { font-size: 12px; font-weight: 600; margin-bottom: 8px; }
  .round-line { display: flex; flex-wrap: wrap; gap: 5px; }
  .round-dot {
    display: inline-flex; align-items: center; gap: 4px; padding: 5px 8px;
    border-radius: 5px; font-size: 11px; font-variant-numeric: tabular-nums;
  }
  .round-dot b { font-weight: 500; }
  /* 예외 인원 수 — 빨강은 '아직 안 봤다' 가 아니라 '문제가 있었다' 예요 */
  .round-dot i { font-style: normal; font-weight: 700; color: #e53e3e; }
  .rs-done { background: #f0fdf4; color: #16a34a; }
  .rs-now { background: var(--text-primary); color: #fff; }
  .rs-missed { background: #fff5f5; color: #e53e3e; }
  .rs-soon { background: #f0f0f0; color: var(--text-muted); }

  /* 꺼둔 상태 — 지난 기록 때문에 남겨두지만 이제 고를 수 없어요 */
  .linked-item.status-off { opacity: 0.55; }

  /* ── 출석부: 인쇄용 체크표 ── */
  .check-table { width: 100%; border-collapse: collapse; font-size: 10px; }
  .check-table th, .check-table td { border-bottom: 0.5px solid var(--line); padding: 6px 4px; text-align: center; }
  .check-table th { font-size: 9px; color: var(--text-muted); font-weight: 400; letter-spacing: 0.3px; }
  .check-table td.check-name { text-align: left; white-space: nowrap; }
  .check-table td.check-cell { min-width: 26px; height: 22px; }
  .check-room-title { font-size: 11px; font-weight: 600; margin: 18px 0 8px; }
  /* 공석 색 규칙 (스펙 5번): 정기=빨강, 비정기=앰버, 둘 다면 비정기 우선 */
  .check-absent-regular { color: #e53e3e; }
  .check-absent-irregular { color: #d97706; }

  @media print {
    /* 인쇄할 땐 화면 전용 요소를 전부 숨겨요 (스펙 탭③) */
    .navbar, .nb-dim, .topbar, .tabs, .action-row, .room-picker, .no-print { display: none !important; }
    body { display: block; height: auto; overflow: visible; }
    .main, .body-wrap, .detail-panel { display: block; overflow: visible; height: auto; padding: 0; }
    .check-table { font-size: 9px; }
    .check-table td.check-cell { height: 26px; }
    .check-room-title { page-break-before: always; }
    .check-room-title:first-of-type { page-break-before: auto; }
  }

  /* ── 성적 입력 표 ──
     과목이 6개고 과목마다 항목이 최대 4개라 열이 많아요.
     가이드대로 배경 없이 0.5px 선으로만 구분하고, 가로 스크롤로 넘겨봐요. */
  .table-scroll { overflow-x: auto; scrollbar-width: thin; }
  .gtable { border-collapse: collapse; font-size: 11px; white-space: nowrap; }
  .gtable th, .gtable td { border-bottom: 0.5px solid var(--line); padding: 8px 6px; text-align: center; }
  .gtable thead th { font-size: 10px; color: var(--text-muted); font-weight: 400; letter-spacing: 0.3px; }
  /* 과목 묶음 사이에만 세로선을 그어 어디까지가 한 과목인지 보이게 해요 */
  .gtable .subject-start { border-left: 0.5px solid var(--line); }
  /* 학생 이름 칸도 나머지와 같이 가운데 정렬해요 */
  .gtable td.name-cell { font-size: 12px; font-weight: 500; position: sticky; left: 0; background: #fff; white-space: nowrap; min-width: 88px; }
  .gtable th.name-cell { position: sticky; left: 0; background: #fff; min-width: 88px; }
  /* 입력 칸 — 가이드 0-4 대로 테두리 없이 */
  .gcell { width: 52px; font-size: 12px; font-family: inherit; color: var(--text-primary); border: none; outline: none; background: transparent; text-align: center; padding: 2px 0; }
  .gcell:focus { border-bottom: 0.5px solid var(--text-primary); }
  /* 고친 줄을 표시해요 */
  /* 합계 열과 통계 줄 — 입력칸이 아니라 계산된 값이라 옅게 */
  .gtable td.sum-cell { color: var(--text-secondary); font-weight: 500; }
  .gtable tfoot .stat-row td { color: var(--text-muted); border-top: 0.5px solid var(--line); }
  .gtable tfoot .stat-row td.name-cell { color: var(--text-secondary); font-weight: 500; }
  /* Folio 사용량 '기능별' 표 — 합계 줄 폭(520px)을 꽉 채우고 양 끝 칸은 안쪽 여백 없이 (원장 지정 2026-10-20) */
  .usage-mode .gtable { width: 100%; }
  .usage-mode .gtable th:first-child, .usage-mode .gtable td:first-child { text-align: left; padding-left: 0; }
  .usage-mode .gtable th:last-child, .usage-mode .gtable td:last-child { text-align: right; padding-right: 0; }

  .gtable tr.changed td.name-cell { color: #38a169; }
  .gtable tr.changed td.name-cell::after { content: ' •'; color: #38a169; }

  /* ── 성적 그래프 ──
     과목별 백분위 추이. 가이드 1번 팔레트의 색만 써요.
     (원본의 색은 색각 이상 검증에서 "회색으로 읽힘"으로 걸려서 바꿨어요) */
  .chart-wrap { position: relative; margin: 8px 0 4px; }
  .chart-svg { display: block; width: 100%; height: auto; }
  .chart-grid { stroke: var(--line); stroke-width: 0.5; }
  .chart-axis { fill: var(--text-muted); font-size: 9px; }
  .chart-line { fill: none; stroke-width: 2; }
  .chart-dot { stroke: #fff; stroke-width: 2; }
  /* 값은 색이 아니라 글자 토큰을 써요 (색은 옆의 점이 담당해요) */
  .chart-readout { font-size: 11px; color: var(--text-secondary); min-height: 18px; margin-top: 6px; }
  .chart-readout .lg { display: inline-flex; align-items: center; gap: 5px; margin-right: 14px; }
  .chart-readout .dot { width: 6px; height: 6px; border-radius: 50%; display: inline-block; }
  .chart-legend { display: flex; gap: 16px; flex-wrap: wrap; font-size: 11px; color: var(--text-muted); margin-bottom: 10px; }
  .chart-legend .lg { display: inline-flex; align-items: center; gap: 6px; }
  .chart-legend .dot { width: 6px; height: 6px; border-radius: 50%; display: inline-block; }
  .chart-hover { stroke: var(--text-muted); stroke-width: 0.5; stroke-dasharray: 2 2; }

  @media print {
    .report-page { page-break-after: always; }
    .report-page:last-child { page-break-after: auto; }
  }

  /* ── 학원 설정 왼쪽 현황 ──
     짧은 라벨/값 줄을 쌓아요. 260px 안에 들어가야 해서 세로로 배치해요. */
  .stat-row { display: flex; align-items: baseline; justify-content: space-between; padding: 9px 0; }
  .stat-label { font-size: 11px; color: var(--text-muted); }
  .stat-value { font-size: 13px; font-weight: 500; }
  .stat-group { margin-bottom: 18px; }
  .stat-group-title { font-size: 10px; color: var(--text-muted); letter-spacing: 0.4px; text-transform: uppercase; margin-bottom: 6px; }

  /* ── 학습 스케줄 (학생 상세 > 학습 스케줄 탭, docs/decisions/schedule.md) ──
     주간 시간표 블록(.sch-block)은 좌석 그리드와 같은 가이드 0-1 의 명시적 예외예요 (2026-09-15 원장 결정).
     7일 × 36칸을 한눈에 훑어야 해서 블록을 과목색(파스텔)으로 채우고 글자는 그 계열의 진한 색으로 둬요.
     색은 가이드 1번 "과목 전용 색" — 상태 색(초록·주황·빨강…)과 헷갈리지 않게 따로 뒀어요.
     예외는 블록에만 해당해요. 격자 칸은 표처럼 얇은 선만, 오른쪽 편집 칸·교재 목록·메모는 표준 원칙 그대로예요. */
  .tabs.sch-subtabs { margin-bottom: 0; }
  .tabs.sch-day-tabs { margin-bottom: 14px; }
  .sch-empty { font-size: 11px; color: var(--text-muted); padding: 8px 0; }

  /* 왼쪽 시간표(넓게) + 오른쪽 편집·교재·메모 칸. 출석부 좌석 현황과 같은 구조예요.
     align-items:stretch 라 세로 구분선이 아래까지 이어지고, 위로는 하위 탭 밑줄에 닿아요. */
  .sch-layout { display: flex; align-items: stretch; min-height: calc(100vh - 300px); }
  .sch-main { flex: 1; min-width: 0; padding: 18px 28px 24px 0; }
  .sch-side { width: 340px; flex-shrink: 0; padding: 18px 0 24px 40px; }
  .sch-side .form-field { flex: 1 1 120px; }
  .sch-side .picker-list { max-height: 240px; overflow-y: auto; }
  /* 여러 줄 칸도 1줄 높이로 시작해 쓰는 만큼 늘어나요 (원장 요청 — 기본 3줄은 밑줄이 너무 멀었어요) */

  /* 과목별 학습 시간 요약 줄 — 차트가 아니라 글자 (스펙 4-4).
     출석부 요약 줄의 범례(.sumlegend)처럼 과목색 점 + 오른쪽 정렬 (원장 요청 2026-09-15) */
  .sch-summary { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 6px 20px; min-height: 20px; margin-bottom: 14px; font-size: 12px; color: #6e6e6e; }
  .sch-summary .lg { display: inline-flex; align-items: center; gap: 6px; }
  .sch-summary .lg b { font-weight: 600; color: var(--text-primary); }
  .sch-summary .dot { width: 6px; height: 6px; border-radius: 50%; display: inline-block; flex-shrink: 0; background: var(--sch-bg); }
  .sch-summary .sch-sum-empty { color: var(--text-muted); }

  /* 격자: 왼쪽 시각 열 + 요일 열(주간 7개, 좁은 화면 1개). 칸은 표처럼 선으로만 나눠요.
     줄 높이(26px 머리 + 24px 칸)는 student-schedule.js 의 SCH_HEAD_HEIGHT · SCH_ROW_HEIGHT 와 같아야 해요 (끌기 계산).
     touch-action: pan-y — 마우스는 끌어서 시간을 고르고, 손가락은 격자 위에서도 위아래로 넘길 수 있게 해요. */
  .sch-grid { display: grid; grid-template-columns: 44px repeat(var(--days, 7), minmax(0, 1fr)); grid-template-rows: 26px repeat(36, 24px); border-bottom: 0.5px solid var(--line); user-select: none; touch-action: pan-y; }
  .sch-head { grid-row: 1; display: flex; align-items: center; justify-content: center; font-size: 11px; color: var(--text-muted); }
  /* 오늘 요일은 요일 글자만 빨강 굵게 (원장 요청 2026-09-15 — 세로줄 배경은 지나쳤어요. 가이드 0-6 예외) */
  .sch-head.today { color: #e53e3e; font-weight: 700; }
  .sch-time { grid-column: 1; font-size: 10px; color: var(--text-muted); text-align: right; padding: 2px 8px 0 0; }
  .sch-cell { border-left: 0.5px solid var(--line); cursor: pointer; transition: background 0.12s; }
  .sch-cell.hour { border-top: 0.5px solid var(--line); }
  /* 반투명이라 오늘 세로줄 배경 위에서도 hover 가 보여요 */
  .sch-cell:hover { background: rgba(0,0,0,0.035); }
  .sch-block { position: relative; z-index: 1; margin: 1px 2px; padding: 3px 6px; border-radius: 3px; overflow: hidden; color: var(--sch-ink, #333); font-size: 11px; line-height: 1.3; cursor: pointer; transition: opacity 0.12s; }
  .sch-block:hover { opacity: 0.85; }
  .sch-block .nm { font-weight: 600; }
  /* 학생이 앱에서 직접 잡은 계획 표시 (2026-09-19) — 굵기만 낮춰 과목 이름보다 뒤로 */
  .sch-block .nm .by { font-weight: 400; opacity: 0.75; }
  .sch-block .sub { opacity: 0.85; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* 블록을 누르면 그 블록만 또렷하고 나머지는 흐리게 — 테두리를 씌우지 않아요 (출석부 좌석과 같음, 원장 요청) */
  /* 파스텔 배경은 20% 로 흐리면 흰 바탕과 똑같아져 블록이 사라져요 (2026-09-19 파스텔로 바꾸며 40% 로 올림).
     색보다 글자가 흐려지는 효과가 커서, 선택한 블록만 글자가 또렷하게 남아요. */
  /* ── 일정 달력 (원장 지정 2026-10-12 · docs/decisions/calendar.md) — 예전 세로 시간 격자 대신 ──
     칸 사이 세로선 · 박스 없음. 날짜마다 위에 검은 가로선 1줄 · 큰 두 자리 숫자. 일요일 · 공휴일은 빨강(흑백 원칙 예외 · 원장 지정) */
  .sch-grid.cal { display: block; border-bottom: none; touch-action: auto; user-select: auto; }
  .cal-head { display: flex; align-items: center; gap: 12px; margin-bottom: 30px; }
  /* 월 넘기기 ‹ • › 는 오른쪽 끝 · '일정 추가' 바로 앞 (원장 지정 2026-10-13) */
  .cal-title { font-size: 24px; font-weight: 800; letter-spacing: -0.4px; margin-right: auto; }
  .cal-nav { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; cursor: pointer; color: var(--text-primary); }
  .cal-nav:hover { opacity: 0.6; }
  .cal-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--text-primary); display: block; }
  .cal-add { margin-left: 18px; font-size: 12px; font-weight: 400; cursor: pointer; color: var(--text-primary); }
  .cal-add:hover { color: #e53e3e; }
  .cal-week, .cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); column-gap: 14px; }
  .cal-week div { font-size: 10px; font-weight: 600; color: var(--text-muted); letter-spacing: 0.4px; padding-bottom: 6px; }
  .cal-grid { row-gap: 16px; }
  .cal-cell { border-top: 1px solid var(--text-primary); padding-top: 5px; min-height: 86px; cursor: pointer; }
  .cal-cell.out { opacity: 0.4; }
  /* 오늘 — 연한 회색 칸 (원장 지정 2026-10-13 — 점만으로는 잘 안 보였어요) */
  .cal-cell.cal-is-today { border-left: none; border-right: none; border-bottom: none; border-radius: 0; background: #f4f4f4; padding-left: 6px; padding-right: 6px; }
  .cal-cell.cal-is-sel { border-top-width: 3px; padding-top: 3px; }
  /* 칸이 좁으면 공휴일 이름은 숫자 아래 줄로 — 한 줄에 우겨 넣으면 이름 칸이 0px 이 돼 '03 :' 만 보였어요 (2026-10-19 사용 점검 B-12) */
  .cal-num { font-size: 18px; font-weight: 500; font-variant-numeric: tabular-nums; display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 6px; }
  .cal-cell.cal-is-today .cal-num, .cal-cell.cal-is-sel .cal-num { font-weight: 800; }
  .cal-red { color: #e53e3e; }
  .cal-hol { font-size: 10px; font-weight: 400; color: #e53e3e; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 0 1 auto; min-width: 0; max-width: 100%; }
  .cal-ev { margin-top: 4px; font-size: 10.5px; font-weight: 400; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .cal-more { font-size: 10px; color: var(--text-secondary); text-decoration: underline; margin-top: 4px; }
  .cal-list-title { font-size: 10.5px; font-weight: 700; color: var(--text-muted); letter-spacing: 0.8px; margin: 26px 0 4px; }
  .cal-row { display: flex; gap: 10px; align-items: center; padding: 11px 0; border-bottom: 0.5px solid var(--line); }
  .cal-time { font-size: 11.5px; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
  .cal-row .dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex-shrink: 0; background: var(--sch-bg); }
  .cal-what { font-size: 12px; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .cal-sub { color: var(--text-secondary); margin-left: 8px; }
  .sch-grid.focused .sch-block { opacity: 0.4; }
  .sch-grid.focused .sch-block:hover { opacity: 0.65; }
  .sch-grid.focused .sch-block.sel { opacity: 1; }
  /* 새로 고른 시간 범위. 과목을 고르기 전엔 회색, 고르면 아래 과목 색이 덮어써요 (그래서 과목 색보다 먼저 적어요).
     누르기·끌기를 방해하지 않게 마우스를 통과시켜요. */
  .sch-ghost { position: relative; z-index: 2; margin: 1px 2px; border-radius: 3px; background: var(--sidebar-active); pointer-events: none; }
  /* 과목색 = 파스텔 배경(--sch-bg) + 그 계열의 진한 색(--sch-ink). 글자와 요약 줄의 색 점이 진한 색을 써요.
     (2026-09-19 원장 요청 '너무 칙칙해' 로 채운 진한 색에서 파스텔로 바꿨어요. 글자는 흰색에서 진한 색으로.)
     모든 쌍이 글자 대비 4.5:1 이상이에요. 값을 바꾸면 대비를 다시 재세요. */
  /* 과목 색 — 학생이 과목마다 고르는 10색 중 기본값 (원장 지정 2026-10-13 · backend/utils/subjectColors.js).
     학생 화면을 열면 student-schedule.js 가 그 학생이 고른 색으로 덮어써요 (#schColors).
     --sch-bg = 칠할 색 · --sch-ink = 그 위 글자색 (흰 / 검정 중 대비 4.5 넘는 쪽) */
  .sch-KOREAN  { --sch-bg: #D56F15; --sch-ink: #111111; background: var(--sch-bg); }
  .sch-MATH    { --sch-bg: #1652DF; --sch-ink: #FFFFFF; background: var(--sch-bg); }
  .sch-ENGLISH { --sch-bg: #6012BA; --sch-ink: #FFFFFF; background: var(--sch-bg); }
  .sch-SOCIAL  { --sch-bg: #91E817; --sch-ink: #111111; background: var(--sch-bg); }
  .sch-SCIENCE { --sch-bg: #0C7930; --sch-ink: #FFFFFF; background: var(--sch-bg); }
  .sch-OTHER   { --sch-bg: #890F95; --sch-ink: #FFFFFF; background: var(--sch-bg); }

  /* 메모 탭 (편집기 모양은 아래 "서식 있는 글" .rich-*) */
  .sch-memo-note { margin-top: -6px; margin-bottom: 14px; }

  /* 상담 탭만 좌·우를 **반씩** 나눠요 (원장 지정 2026-09-23).
     스케줄링 탭은 격자가 넓어야 해서 .sch-side 340px 를 그대로 둬요 — 그래서 이 탭에만 붙이는 클래스예요. */
  .consult-split .sch-main { flex: 1 1 0; }
  .consult-split .sch-side { width: auto; flex: 1 1 0; }

  /* ── 서식 있는 글 편집기 (rich-text.js) — 학생 메모 · 공지 작성. 가이드 5번 "서식 있는 글" ──
     글 칸을 사방 회색 테두리 상자로 두는 건 검색칸(0-4)과 같은 예외예요 (원장 요청 2026-09-15 —
     글을 쓰는 자리가 한눈에 보이게).
     도구줄은 묶음마다 한 줄씩 쌓는 격자예요 — 한 줄로 늘어놓으면 좁은 칸(공지 작성)에서 줄글처럼 흘러내려
     어디까지가 한 묶음인지 안 보였어요. 첫 열은 항목 이름, 버튼은 세로로 줄이 맞아요 (원장 피드백 2026-09-15).
     열 너비는 각 열에서 가장 긴 버튼에 맞춰져서, 칸이 좁아도 줄이 흐트러지지 않아요.
     도구줄은 글 칸 오른쪽 칸(서식 칸)에 둬요 — 맥 Pages 의 서식 패널처럼 (원장 요청 2026-09-15). */
  .rich-tools { display: grid; grid-template-columns: max-content repeat(5, max-content); column-gap: 14px; row-gap: 10px; align-items: center; margin-bottom: 12px; user-select: none; }
  /* 항목 이름은 필드 라벨(12px · 포인트색)보다 한 단계 아래 — "내용" 같은 칸 이름과 위계가 섞이지 않게.
     그래도 흐리지 않게 진한 회색 · 굵게 둬요 (너무 작고 흐리다는 피드백도 함께 반영) */
  /* 항목 이름(정렬·크기·굵기·색)은 검은 테두리 투명 박스로 둬요 (2026-09-17 원장 요청).
     옆의 고르는 글자들과 섞여 보여서 묶음 경계가 흐렸어요. 글 칸(.rich-editor)의 상자
     디자인만 가져오고, 여백은 글자 크기에 맞게 좁혀요 (위계를 뜻하는 건 아니에요). */
  .rich-label { grid-column: 1; font-size: 11px; font-weight: 600; color: var(--text-primary); padding: 2px 6px; border: 1px solid var(--text-primary); border-radius: 4px; background: transparent; justify-self: start; }
  .rich-tool { font-size: 11px; color: var(--text-secondary); cursor: pointer; }
  .rich-hint { margin-top: -6px; margin-bottom: 16px; }
  .rich-tool:hover { text-decoration: underline; }
  .rich-editor { width: 100%; min-height: 40px; padding: 9px 12px; border: 1px solid #d0d0d0; border-radius: 8px; outline: none; font-size: 13px; line-height: 1.7; color: var(--text-primary); caret-color: var(--text-primary); background: transparent; word-break: break-word; transition: border-color 0.15s; }
  .rich-editor:focus { border-color: var(--text-primary); }
  .rich-editor:empty::before { content: attr(data-placeholder); color: #d0d0d0; }
  .rich-editor:focus::before { content: ''; }
  /* 글 사이 사진 (2026-10-19) — 줄 하나를 차지해요. 편집 칸에서는 오른쪽 위 빨강 × 로 글에서만 빼요 */
  .rich-img { position: relative; margin: 8px 0; user-select: none; }
  .rich-img img { display: block; max-width: 100%; max-height: 480px; border-radius: 8px; background: var(--surface2, #f2f2f2); }
  .rich-thumb { grid-column: 2 / -1; display: inline-flex; align-items: flex-start; gap: 6px; }
  .rich-thumb:empty { display: none; }
  .rich-thumb img { width: 96px; height: 54px; object-fit: cover; border-radius: 6px; background: var(--surface2, #f2f2f2); }
  .rich-img-x { position: absolute; top: 6px; left: 6px; width: 22px; height: 22px; border-radius: 11px; background: #fff; color: #e53e3e; font-size: 15px; line-height: 22px; text-align: center; cursor: pointer; }
  .form-field:has(.rich-editor) { max-width: 720px; }
  /* 공지 작성: 제목 밑줄을 아래 글 칸과 같은 폭(720px)으로 맞춰요 (2026-09-17 원장 요청).
     제목은 .form-field.wide 라 560px 이었고 글 칸은 720px 이어서, 밑줄이 박스보다
     짧아 어긋나 보였어요. */
  #composeForm .form-field.wide { max-width: 720px; }

/* ── 출결 키오스크 (2026-09-23) ──────────────────────────
   학원 입구에 두는 화면. 멀리서도 보이게 크고, 손가락으로 눌러요.
   로그인이 없어서 사이드바도 없어요 (solist-pay.html 과 같은 단독 화면). */
.kiosk { min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 32px 20px; text-align: center; }
.kiosk-title { font-size: 24px; font-weight: 600; color: var(--text-primary); }
.kiosk-sub { font-size: 14px; color: var(--text-muted); margin-top: 8px; }
.kiosk-msg { font-size: 14px; color: #e53e3e; margin-top: 16px; opacity: 0; transition: opacity 0.15s; }
.kiosk-msg.show { opacity: 1; }
.kiosk-code { font-size: 40px; letter-spacing: 14px; color: var(--text-primary); margin: 28px 0 24px; font-variant-numeric: tabular-nums; }

/* 번호판 — 세 칸씩 네 줄 */
.kiosk-pad { display: grid; grid-template-columns: repeat(3, 92px); gap: 12px; }
.kiosk-key { display: flex; align-items: center; justify-content: center; height: 72px; font-size: 24px; color: var(--text-primary);
  border: 1px solid var(--border); border-radius: 12px; cursor: pointer; user-select: none; transition: background 0.12s; }
.kiosk-key:active { background: var(--sidebar-active); }
.kiosk-key-go { background: var(--text-primary); color: #fff; border-color: var(--text-primary); font-size: 18px; }

/* 외출인지 하원인지 고르는 두 칸 */
.kiosk-choice { display: flex; gap: 16px; margin-top: 24px; }
.kiosk-big { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; width: 148px; height: 120px;
  font-size: 22px; font-weight: 600; color: var(--text-primary); border: 1px solid var(--text-primary); border-radius: 16px;
  cursor: pointer; user-select: none; transition: background 0.12s, color 0.12s; }
.kiosk-big:active { background: var(--text-primary); color: #fff; }
.kiosk-big small { font-size: 12px; font-weight: 400; color: var(--text-muted); }
.kiosk-big:active small { color: rgba(255,255,255,0.75); }

/* 결과 */
.kiosk-done { font-size: 32px; font-weight: 600; color: var(--text-primary); margin-bottom: 10px; }

/* ── 상담 기록 목록 (2026-09-23) ──────────────────────────
   날짜마다 한 줄. 박스로 감싸지 않고 줄 사이 0.5px 선으로 나눠요 (가이드 0-1). */
/* 상담 목록 — 줄마다 제목 한 줄. 누르면 오른쪽 칸에서 읽고 고쳐요 (본문은 목록에 펼치지 않아요) */
.consult-item { padding: 14px 0; cursor: pointer; }
.consult-item.active { background: var(--sidebar-active); border-radius: 6px; padding-left: 10px; padding-right: 10px; }
.consult-title { font-size: 13px; color: var(--text-primary); margin-bottom: 5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.consult-head { display: flex; align-items: center; gap: 10px; }
.consult-date { font-size: 12px; color: var(--text-muted); }
.consult-who { font-size: 11px; color: var(--text-muted); margin-right: auto; }
.consult-draft { font-size: 11px; color: var(--text-secondary); background: var(--sidebar-active); border-radius: 4px; padding: 1px 6px; }
.consult-item.active .consult-draft { background: var(--bg, #fff); }

/* AI 정리 (2026-10-10 · AI 스펙 2.2) — 원본 메모와 정리본을 나란히. 원본은 고칠 수 없는 회색 글자 */
.consult-pair.paired { display: flex; gap: 20px; align-items: stretch; }
.consult-pair.paired > * { flex: 1 1 0; min-width: 0; }
.consult-orig-text { white-space: pre-wrap; font-size: 13px; line-height: 1.7; color: var(--text-secondary); padding: 10px 0; border-top: 0.5px solid var(--line); }
.consult-ai-note { margin: 8px 0 18px; }
.consult-follow { display: flex; align-items: center; gap: 12px; }
.consult-follow .field-input { flex: 1; min-width: 0; }
.consult-follow-done { font-size: 12px; color: var(--text-secondary); padding: 4px 10px; border-radius: 6px; cursor: pointer; user-select: none; white-space: nowrap; }
.consult-follow-done.active { background: var(--sidebar-active); color: var(--text-primary); font-weight: 600; }
#consultActions { gap: 14px; margin-top: 18px; }
#consultActions .busy { opacity: 0.5; pointer-events: none; }

/* 상담 전 브리핑 (AI 스펙 3절) — 한 눈에. 박스 없이 줄과 여백만 (가이드 0-1).
   확인이 필요한 줄(warn)만 굵게 — 색으로 겁주지 않아요 (빨강은 지우기 전용 · 가이드 0-6) */
.brief { margin-bottom: 26px; }
.brief:empty { display: none; }
.brief-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.brief-range { font-size: 11.5px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.brief-line { display: flex; align-items: baseline; gap: 12px; font-size: 13px; line-height: 1.6; color: var(--text-secondary); padding: 3px 0; font-variant-numeric: tabular-nums; }
.brief-line > span:first-child { flex: 1; min-width: 0; }
.brief-line.warn { color: var(--text-primary); font-weight: 600; }
.brief-done { font-size: 12px; font-weight: 500; color: var(--text-primary); cursor: pointer; white-space: nowrap; }
.brief-done:hover { color: var(--point); }
.brief-past { margin-top: 12px; padding-top: 12px; border-top: 0.5px solid var(--line); }
.brief-sub { font-size: 11.5px; color: var(--text-muted); margin-bottom: 4px; }
.brief-latest { font-size: 13px; line-height: 1.7; color: var(--text-primary); white-space: pre-wrap; }
.brief-earlier { display: flex; gap: 10px; font-size: 12.5px; line-height: 1.6; color: var(--text-secondary); margin-top: 4px; }
.brief-date { color: var(--text-muted); min-width: 34px; font-variant-numeric: tabular-nums; }
.brief-link { cursor: pointer; }
.brief-link:hover { color: var(--point); }
.brief-wait { font-size: 12.5px; color: var(--text-muted); }

/* 개인정보 입력 안내 (2026-10-07, SOLIST_PRIVACY_TERMS.md).
   자유 서술 칸 아래에 **상시 노출**해요. 사고가 났을 때 "안전조치 의무를 다했는가" 에서
   안내문만 띄운 것과 아무것도 안 한 것이 갈려요. 눈에 띄되 시끄럽지 않게 — 작은 회색 글이에요 */
.privacy-note { margin-top: 7px; font-size: 11.5px; color: var(--text-secondary); }

/* 개인정보 동의 문구 보기 (2026-10-08). 원장이 PC 에서 앱 글을 그대로 읽는 자리예요.
   박스를 두르지 않아요 (디자인 가이드) — 왼쪽 얇은 선으로만 묶어요 */
.consent-item { margin-bottom: 26px; padding-left: 14px; border-left: 2px solid var(--line); }
.consent-item-title { font-size: 13px; font-weight: 600; color: var(--text-primary); margin-bottom: 4px; }
.consent-item-sum { font-size: 11.5px; color: var(--text-muted); margin-bottom: 14px; }
.consent-sec { margin-bottom: 14px; max-width: 760px; }
.consent-sec-h { font-size: 11.5px; font-weight: 600; color: var(--text-secondary); margin-bottom: 4px; }
.consent-sec-p { font-size: 12px; color: var(--text-secondary); line-height: 1.75; margin-bottom: 3px; }

/* 섹션 난도 — 끌어서 정해요 (원장 지정 2026-10-09). 박스 없이 한 줄: 섹션 이름 · 막대 · 고른 난도 */
.level-row { display: flex; align-items: center; gap: 12px; margin-top: 10px; }
.level-name { width: 140px; font-size: 13px; color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.level-range { flex: 1; max-width: 260px; accent-color: var(--text-primary); cursor: pointer; }
.level-label { width: 48px; font-size: 13px; font-weight: 600; color: var(--text-primary); }

  /* 학생 화면 › 학습 통계 (learning-stats.js · 2026-10-13) — 박스 없이 0.5px 선과 여백으로만 나눠요 */
  .ls-block { padding: 22px 0; border-bottom: 0.5px solid var(--line); }
  .ls-block:first-child { padding-top: 4px; }
  .ls-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
  .ls-head .section-title { margin-bottom: 0; }
  .ls-sub { font-size: 12px; color: var(--text-muted); }
  .ls-chart { margin-top: 16px; }
  .ls-pair { display: flex; flex-wrap: wrap; gap: 28px 48px; margin-top: 16px; }
  .ls-cell { min-width: 180px; }
  .ls-wide { flex: 1; min-width: 300px; }
  .ls-cap { font-size: 12px; color: var(--text-muted); margin-bottom: 10px; }
  .ls-note { font-size: 12px; color: var(--text-muted); padding: 6px 0; }
  .ls-rows { margin-top: 10px; }
  .ls-row { display: flex; align-items: baseline; gap: 14px; padding: 9px 0; border-top: 0.5px solid var(--line); font-size: 13px; }
  .ls-row:first-child { border-top: none; }
  .ls-row-title { color: var(--text-primary); min-width: 90px; }
  .ls-row-date { flex: 1; font-size: 12px; color: var(--text-muted); }
  .ls-row-val { font-weight: 600; color: var(--text-primary); font-variant-numeric: tabular-nums; }

  /* 학생 화면 › 현황 (learning-stats.js · 2026-10-13) — 앱 현황과 같은 카드 줄. 위에서부터 70ms 씩 왼쪽에서 (모션 가이드 22번) */
  .st-head { margin: 22px 0 4px; }
  .st-head:first-child { margin-top: 4px; }
  .st-row { display: flex; align-items: center; gap: 14px; padding: 13px 16px; margin-top: 8px; max-width: 760px;
    background: #F4F4F6; border-radius: 8px; animation: st-in 550ms cubic-bezier(0.33, 1, 0.68, 1) both; }
  .st-project { padding: 12px; }
  @keyframes st-in { from { opacity: 0; transform: translateX(-24px); } to { opacity: 1; transform: none; } }
  @media (prefers-reduced-motion: reduce) { .st-row { animation: none; } }
  .st-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--text-primary); flex: none; }
  .st-main { flex: 1; min-width: 0; }
  .st-line { display: flex; align-items: baseline; gap: 8px; }
  .st-title { font-size: 14px; font-weight: 600; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .st-sub { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
  .st-amount { font-size: 13px; font-weight: 600; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
  .st-thumb { width: 52px; height: 52px; border-radius: 8px; background: #E6E6EB; color: #767676; display: flex; align-items: center; justify-content: center; flex: none; }
  .st-thumb { overflow: hidden; }
  .st-cover { width: 100%; height: 100%; object-fit: cover; display: block; cursor: default !important; }
  .st-bar { position: relative; height: 6px; border-radius: 3px; background: #E6E6EB; margin-top: 9px; overflow: hidden; }
  .st-plan { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 3px; background: rgba(118, 118, 118, 0.45); }
  .st-fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 3px; background: var(--text-primary); }
  .st-care { font-size: 12px; color: #e53e3e; margin-top: 7px; }
  .st-end { text-align: right; min-width: 64px; }
  .st-dday { font-size: 12px; font-weight: 700; color: var(--text-secondary); }
  .st-ratio { font-size: 15px; font-weight: 700; color: var(--text-primary); margin-top: 4px; font-variant-numeric: tabular-nums; }

  /* 학생 화면 › 성적 (student-scores.js · 2026-10-13) — 앱 성적과 같은 그림. 박스 없이 여백 · 0.5px 선 */
  .ss-series { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
  .ss-sub { font-size: 12px; color: var(--text-muted); margin-bottom: 8px; }
  .ss-block { padding: 26px 0; border-bottom: 0.5px solid var(--line); max-width: 980px; }
  .ss-block:last-child { border-bottom: none; }
  .ss-title { font-size: 16px; font-weight: 700; color: var(--text-primary); margin-bottom: 26px; }
  .ss-pairs { display: flex; justify-content: space-between; gap: 16px; }
  .ss-name { font-size: 13px; font-weight: 600; color: var(--text-primary); margin-bottom: 16px; }
  .ss-round-row { display: flex; align-items: flex-end; gap: 16px; margin-top: 14px; }
  .ss-round-row:first-of-type { margin-top: 0; }
  .ss-round-name { width: 80px; padding-bottom: 22px; font-size: 13px; font-weight: 600; color: var(--text-primary); flex: none; }
  .ss-unit { font-size: 11px; font-weight: 400; color: var(--text-muted); margin-top: 2px; }
  .ss-round-bars { overflow-x: auto; }
  .ss-unit-inline { font-size: 11px; color: var(--text-muted); }
  .ss-dots { display: inline-flex; align-items: center; gap: 7px; }
  .ss-dot { width: 6px; height: 6px; border-radius: 50%; background: #E6E6EB; cursor: pointer; display: inline-block; }
  .ss-dot.on { background: var(--text-primary); }
  .ss-arrows { align-items: center; }
  .ss-nav { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
  .ss-round { font-size: 15px; font-weight: 700; color: var(--text-primary); }
  .ss-latest { font-size: 11px; font-weight: 700; color: var(--point); }
  .ss-arrows { margin-left: auto; display: flex; gap: 10px; }
  .ss-arrow { cursor: pointer; color: var(--text-primary); display: inline-flex; }
  .ss-arrow.off { opacity: 0.25; cursor: default; }
  .ss-tbl { width: 100%; max-width: 640px; border-collapse: collapse; font-size: 13px; }
  .ss-tbl th { font-size: 11px; font-weight: 500; color: var(--text-muted); padding: 0 0 10px; border-bottom: 0.5px solid var(--line); text-align: center; }
  .ss-tbl td { padding: 11px 0; text-align: center; font-weight: 600; color: var(--text-primary); font-variant-numeric: tabular-nums; }
  .ss-tbl th:first-child, .ss-tbl td:first-child { text-align: left; font-weight: 400; color: var(--text-secondary); }

/* ═══════════════════════════════════════════════════════════════════════════
   태블릿 톤 (원장 지정 2026-10-19 — "선생님 웹을 앱 '태블릿 UI' 처럼")
   앱 아이패드 화면(mobile/src/theme.js · SOLIST_TOSS_DESIGN_GUIDE.md 2부)의 크기 · 색 · 부품을 웹에 옮겨요.
   이 묶음이 위의 예전 규칙을 **덮어써요** — 묶음째 지우면 예전 모양으로 돌아가요.

   [크기] 화면 전체를 한 단계 키워요 (zoom). 예전 웹 글자는 11 ~ 13px 이라 태블릿(14 ~ 17)보다 한참 작았어요.
          화면마다 숫자가 따로 적혀 있어서(수천 곳) 하나씩 고치는 대신 통째로 키우고, 아래 부품만 따로 맞췄어요.
          아래 px 는 **키우기 전 값**이에요 (화면에는 1.25 배로 보여요).
   [메뉴] 왼쪽 검은 바 대신 머리글 왼쪽에 아이콘을 나란히 (앱 아이패드 시안과 같은 모양 · 원장이 나중에 메뉴 수를 줄여요)
   [카드] '박스 금지' 를 풀었어요 — 요약 · 고르는 목록은 옅은 회색 카드 (그림자 없이 · 모서리 8)
   [입력] 밑줄 대신 채운 칸 (앱 입력칸과 같아요)
   ═══════════════════════════════════════════════════════════════════════════ */
  :root {
    --ui-zoom: 1.25;
    --line: #ECECEE; --text-muted: #767676;
    --surface: #F4F4F6; --surface2: #E6E6EB;
    --sidebar-hover: #F4F4F6; --sidebar-active: #E6E6EB;
  }
  @media (max-width: 1280px) { :root { --ui-zoom: 1.12; } }
  body { zoom: var(--ui-zoom); height: calc(100vh / var(--ui-zoom)); font-size: 12px; background: #fff; }
  /* 화면 틀을 창 네 변에 붙여요 — 높이를 셈하지 않아서 사파리 · 크롬 모두 창에 딱 맞아요 (common.js fitBodyHeight · 2026-10-24) */
  body.fit-screen { position: fixed; inset: 0; height: auto; }
  .col-split { min-height: calc(100vh / var(--ui-zoom) - 240px); }
  .sch-layout { min-height: calc(100vh / var(--ui-zoom) - 300px); }

  /* 머리글 — 왼쪽 메뉴 아이콘 · 오른쪽 채팅 · 알림. 화면 제목 글자는 숨겨요 (고른 아이콘이 지금 자리를 알려줘요) */
  .topbar { height: 56px; gap: 10px; }
  .topbar-title { display: none; }
  .topbar .navbar { width: auto; height: auto; margin: 0 0 0 -6px; border-radius: 0; background: transparent; flex-direction: row; align-items: center; flex: 1 1 auto; min-width: 0; z-index: 1; }
  .topbar .nb-logo, .topbar .nb-dim { display: none; }
  .topbar .nb-menu { flex: 0 1 auto; flex-direction: row; overflow-x: auto; overflow-y: hidden; gap: 2px; padding: 0; width: auto; }
  .topbar .nb-foot { flex-direction: row; width: auto; padding: 0 0 0 2px; gap: 2px; }
  .topbar .nb-item { width: 34px; height: 34px; color: var(--text-secondary); }
  /* 마우스를 올린 칸에 회색을 칠하지 않아요 — 고른 칸(회색)과 헷갈렸어요 (원장 지적 2026-10-19). 올린 표시는 독 움직임 · 글자 색으로 */
  .topbar .nb-item:hover:not(.active) { opacity: 1; background: transparent; color: var(--text-primary); }
  .topbar .nb-item.active { background: var(--surface2); color: var(--text-primary); }
  .topbar .nb-ic { width: 19px; height: 19px; }
  .topbar .nb-ic svg { width: 19px; height: 19px; }
  .topbar-right { flex-shrink: 0; }
  .topbar-icon { color: var(--text-primary); }
  .nb-tip { transform: translateX(-50%); font-size: 11px; }

  /* 구역 제목 · 패널 제목 — 앱 SectionTitle(22) · 큰 제목에 맞춰요 */
  .section-title { font-size: 16px; font-weight: 700; letter-spacing: -0.3px; margin-bottom: 12px; }
  .panel-title { font-size: 19px; font-weight: 700; letter-spacing: -0.4px; margin-bottom: 6px; }
  .panel-sub { font-size: 12px; }

  /* 1차 탭 — 앱 TopTabs: 글자만 · 고른 탭 아래 두께 3 검은 밑줄 · 탭 줄 아래 가는 선 */
  .tabs { border-bottom: 0.5px solid var(--line); margin-left: -12px; }
  .tab { font-size: 14px; padding: 6px 12px 10px; border-bottom-width: 3px; color: var(--text-muted); }
  .tab.active { font-weight: 600; }

  /* 고르기 칩 — 앱 Segs: 회색 칸 · 고른 것은 포인트색 칸 + 흰 글자 */
  .type-options { gap: 6px; }
  /* 박스 규칙 (원장 지정 2026-10-19): 회색 바탕 · 테두리 없음 = 글을 적는 칸 / **흰 바탕 · 검은 테두리 = 고르는 칸 · 2차 메뉴** */
  .type-option { padding: 5px 11px; border-radius: 8px; font-size: 12px; font-weight: 600; color: var(--text-primary); background: #fff; border: 1px solid var(--text-primary); }
  .type-option:hover { background: #fff; color: var(--text-primary); }
  .type-option.active { background: var(--point); color: #fff; }

  /* 입력 — 밑줄 대신 채운 칸 (앱 입력칸) · 누르면 검은 테두리 한 겹 */
  .field-label { font-size: 11px; font-weight: 600; color: var(--text-secondary); letter-spacing: 0; margin-bottom: 6px; }
  .field-input, .field-value, .field-textarea, .picker-input { background: var(--surface2); border: none; border-bottom: none; border-radius: 8px; padding: 8px 11px; min-height: 34px; font-size: 12.5px; }
  .field-input:focus, .field-textarea:focus, .picker-input.open { outline: 1.5px solid var(--text-primary); outline-offset: -1.5px; border-bottom: none; }
  .field-value { background: var(--surface); }
  .search-input { background: var(--surface2); border: none; border-radius: 8px; padding: 8px 11px; font-size: 12.5px; }
  .search-input:focus { outline: 1.5px solid var(--text-primary); outline-offset: -1.5px; }
  .search-input::placeholder, .field-input:empty::before, .field-textarea:empty::before { color: #9a9aa2; }
  .picker-list { border-radius: 8px; border: 0.5px solid var(--line); padding: 4px; }

  /* 버튼 — 앱 할 일 버튼(Cta): 1급 검은 칸 · 2급 흰 바탕 검은 테두리 · 모서리 8 */
  .btn-1st, .btn-2nd, .add-btn { font-size: 12.5px; font-weight: 700; border-radius: 8px; padding: 9px 18px; }
  .btn-2nd, .add-btn { border-width: 1.5px; background: #fff; }
  .add-btn { height: auto; }

  /* 목록 줄 — 고른 줄은 옅은 회색 칸 (앱 고르는 목록) */
  /* 줄을 본문 줄에서 12 안쪽으로 들여 칸처럼 (화면 끝까지 칠하지 않아요) — 글자 자리는 그대로예요 */
  .student-item { border-radius: 8px; padding: 12px 12px; margin: 0 calc(var(--pad-x) - 12px); }
  .student-item:hover { background: var(--surface); }
  .student-item.active { background: var(--surface2); }
  .student-name { font-size: 13px; font-weight: 600; }
  .student-meta { font-size: 11.5px; }

  /* 카드 — 요약 · 덩어리 (앱 card: 옅은 회색 · 모서리 8 · 그림자 없음) */
  .card, .ui-card { background: var(--surface); border-radius: 8px; padding: 16px; }

  /* 필터 줄 — 왼쪽 칩 · 오른쪽 끝 할 일 글자 (앱 FilterChips right · RowAction) */
  .filter-row { display: flex; align-items: center; gap: 10px; }
  .filter-row .type-options { flex: 1; min-width: 0; }
  .row-action { font-size: 12px; font-weight: 600; color: var(--text-primary); cursor: pointer; user-select: none; white-space: nowrap; transition: transform 0.12s; }
  .row-action:hover { transform: scale(1.06); }

  /* 상담 작성 — 채팅 칸이 아니라 **메모장** (원장 지정 2026-10-19 — "적으면서 이야기하니까")
     박스 없이 (원장 지정 2026-10-19 두 번째 — 줄 공책 무늬가 화면을 키우면 줄이 촘촘히 겹쳐 보였어요 · "박스 디자인 하지 말자")
     높이를 넉넉히 · 줄 간격 넓게 · 아래 가는 선 하나로 쓰는 자리만 보여줘요. 아래 서식 도구줄과 사이를 띄워요 */
  #consultMemo { min-height: 280px; padding: 4px 0 14px; border: none; border-radius: 0; background: transparent; border-bottom: 0.5px solid var(--line);
    line-height: 1.9; font-size: 13px; overflow: auto; }
  #consultMemo:focus { outline: none; border-bottom-color: var(--text-primary); }
  #consultMemoTools { margin-top: 16px; }
  .rich-editor { border: none; background: var(--surface2); }
  .rich-editor:focus { outline: 1.5px solid var(--text-primary); outline-offset: -1.5px; }
  .rich-editor + .rich-tools, .rich-tools { margin-top: 14px; }

  /* 머리글 아이콘 독 (모션 가이드 28번) — 커지면 아래로 자라요. 줄은 위에 붙여 두고 넘쳐도 보이게 */
  .topbar .navbar, .topbar .nb-menu, .topbar .nb-foot { overflow: visible; align-items: flex-start; }
  .topbar .nb-menu { overflow-x: visible; }
  .topbar .navbar { align-self: flex-start; margin-top: 11px; z-index: 30; }
  .topbar .nb-item { position: relative; transform-origin: 50% 0; }
  .topbar .nb-item.active { z-index: 1; }

  /* 출석부 좌석 — 태블릿 톤 (원장 지정 2026-10-19): 앉은 자리는 옅은 회색 카드 · 빈자리는 점선 · 모서리 8.
     외출 · 미등원 · 담임 필요의 색 채움은 그대로예요 (좌석 격자 예외 — 누가 나가 있는지 한눈에) */
  .seat { border-radius: 8px; border: 1px solid transparent; }
  .seat.normal { background: var(--surface); border-color: transparent; }
  .seat.normal:hover { background: var(--surface2); }
  .seat.empty { opacity: 1; border: 1px dashed #D2D2D8; background: transparent; }
  .seat.empty .nm, .seat.empty .no { color: #9a9aa2; }
  .seat.empty:hover { background: var(--surface); }

  /* 결제 — 오른쪽 '미리 보기' 를 카드로 (실제 청구서 한 장처럼 보이게) */
  .col-right:has(#issuePreview) { background: var(--surface); border-radius: 8px; padding: 18px 20px; align-self: flex-start; margin-top: 24px; }

  /* 질문 게시판 — 과목 칩 줄 오른쪽 끝에 '질문하기' */
  .qna-filter { padding-right: var(--pad-x); }
  .qna-filter .section-tabs { flex: 1; min-width: 0; }
  .qna-filter .section-tabs.tabs { margin-left: 8px; }

  /* 전체 현황 — 숫자 묶음을 카드로 (앱 대시보드 요약 칸 · 태블릿 톤 2026-10-19) */
  .stat-group { background: var(--surface); border-radius: 8px; padding: 12px 16px 6px; margin-bottom: 12px; }
  .stat-group-title { font-size: 11.5px; font-weight: 600; color: var(--text-secondary); margin: 0 0 4px; }
  .stat-row { padding: 7px 0; }
  .stat-value { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }

  /* 상담 예약 — 기다리는 신청 줄을 카드로 (눌러서 고르는 목록 · 태블릿 톤) */
  #askList .day-item { background: var(--surface); border-radius: 8px; padding: 12px 14px; margin-bottom: 8px; }
  #askList .day-item:hover { background: var(--surface2); }

  /* ── 2026-10-19 원장 지정 (세 번째) ── */
  /* '무언가를 더하는' 버튼은 모두 같은 모양 — 흰 바탕 · 검은 테두리 칸 안의 + (이름은 마우스를 올리면 · 읽어 주는 이름 aria-label) */
  .add-box { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; flex-shrink: 0; border: 1.5px solid var(--text-primary); border-radius: 8px; background: #fff; color: var(--text-primary); cursor: pointer; user-select: none; transition: background 0.12s; }
  .add-box:hover { background: var(--surface); }
  .add-box svg { width: 16px; height: 16px; }
  .cal-add-box { margin-left: 10px; }

  /* 왼쪽 목록 칸 — 검색 · 필터 · 안내 · 목록 줄이 **같은 폭**이에요 (줄 상자의 왼쪽 · 오른쪽 끝에 모두 맞춰요) */
  .list-panel .list-search { padding-left: calc(var(--pad-x) - 12px); padding-right: calc(var(--pad-x) - 12px); }
  .list-panel .list-search.filter-row { padding-bottom: 12px; }
  .consent-warn { margin: 0 calc(var(--pad-x) - 12px) 8px; border-radius: 8px; padding: 10px 12px; }

  /* 검은 구분선은 머리글 아래 하나 · 왼쪽 목록 칸 오른쪽 세로선은 **회색** — 1차 메뉴 아래 가로선과 같은 색 · 굵기 (원장 지정 2026-10-19) */
  .topbar { border-bottom: 1px solid var(--text-primary); }
  .body-wrap > .list-panel { border-right: 0.5px solid var(--line); }
  /* 나란한 칸 사이 세로선 — 선은 칸의 **글이 시작하는 높이부터** 그려요. 탭 아래 칸은 탭 줄 쪽으로 당겨 붙여 둬서(-28)
     테두리로 그리면 선이 탭의 가로줄을 뚫고 올라갔어요 (원장 지적 2026-10-19) */
  .col-split > .col + .col { padding-left: 28px; position: relative; }
  /* 나란한 칸 사이 · 구역 사이 검은 선은 없앴어요 (원장 지정 2026-10-19 — 검은 선은 머리글 아래 · 왼쪽 목록 칸에만) */

  /* 상담 메모 — 검은 테두리 · 모서리는 앱 입력칸과 같은 8 (원장 지정 2026-10-19) */
  #consultMemo { border: 1px solid var(--text-primary); border-radius: 8px; padding: 14px 16px; }
  #consultMemo:focus { outline: none; border-width: 1.5px; padding: 13.5px 15.5px; }

  /* 날짜 고르기 달력 (common.js attachDatePicker · 원장 지정 2026-10-19) — 흰 바탕 · 검은 글자 · 검은 테두리 */
  .dp-face { cursor: pointer; user-select: none; }
  .dp-face.dp-empty { color: #9a9aa2; }
  .form-field:has(.dp-face) { position: relative; }
  .dp-pop { position: absolute; z-index: 120; margin-top: 6px; width: 260px; background: #fff; color: var(--text-primary); border: 1px solid var(--text-primary); border-radius: 8px; padding: 12px; }
  .dp-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
  .dp-title { font-size: 13px; font-weight: 700; }
  .dp-nav { display: inline-flex; width: 26px; height: 26px; align-items: center; justify-content: center; border-radius: 8px; cursor: pointer; }
  .dp-nav:hover { background: var(--surface); }
  .dp-week, .dp-grid { display: grid; grid-template-columns: repeat(7, 1fr); text-align: center; }
  .dp-week span { font-size: 10.5px; font-weight: 600; color: var(--text-secondary); padding: 4px 0 6px; }
  .dp-day { font-size: 12px; height: 30px; line-height: 28px; margin: 1px; border-radius: 8px; border: 1px solid transparent; cursor: pointer; font-variant-numeric: tabular-nums; }
  .dp-day:hover { background: var(--surface); }
  .dp-day.dp-out { color: #b4b4bb; }
  .dp-sun { color: #C8323B; }
  .dp-day.dp-out.dp-sun { color: #e6a3a7; }
  .dp-day.dp-today { border-color: var(--text-primary); font-weight: 600; }
  .dp-day.dp-sel { background: var(--text-primary); color: #fff; font-weight: 700; }


  /* 화면 아래 여백 = 머리글 높이만큼 (원장 지정 2026-10-19 — 예전엔 아래 20% 가 통째로 비어 보였어요) */
  /* 아래 여백은 스크롤 **내용의 끝**에 둬요 — 화면 바깥에 두면 마지막 줄(연결된 학부모 등)이 잘렸어요 (원장 지적 2026-10-19) */
  .detail-panel, .student-list, .notice-important, .list-panel > .student-list { padding-bottom: 56px; }

  /* 1차 탭 밑줄 — 미끄러지는 검은 줄 하나 (common.js setupTabInks · 모션 가이드 2번). 탭마다의 밑줄은 숨겨요 */
  .tabs { position: relative; }
  .tab.active { border-bottom-color: transparent; }
  .tab-ink { position: absolute; left: 0; bottom: -0.5px; height: 3px; width: 0; border-radius: 1.5px; background: var(--text-primary); pointer-events: none; opacity: 0; will-change: transform, width; }

  /* 화면 맨 위 탭(Points 학생 · 주문 · 콘텐츠) — 머리글 선과 붙지 않게 · 탭 아래 가는 선이 화면 끝까지 */
  .subtabs.tabs { border-bottom: 0.5px solid var(--line); }
  /* 맨 위 탭 아래 화면 — 남은 높이를 다 채워요 (세로선이 목록 길이에서 끊기지 않게 · 아래 여백은 다른 화면과 같게) */
  .sub-panel.active { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
  .sub-panel.active > .body-wrap { flex: 1 1 auto; min-height: 0; }

  .dp-face.dp-off { opacity: 0.5; cursor: default; }
  .dp-day.dp-dis { color: #cfcfd5; cursor: default; }
  .dp-day.dp-dis:hover { background: transparent; }
  .linked-item:has(.dp-face) { position: relative; }
  .linked-item .dp-face { flex: 0 1 150px; }

  /* 머리글 아이콘 — 올리면 그 아이콘만 살짝 아래로 (원장 지정 2026-10-19 · 독 대신) · 220ms EASE */
  .topbar .nb-item { transition: transform 220ms cubic-bezier(0.25, 0.1, 0.25, 1); }
  .topbar .nb-item:hover { transform: translateY(4px); }
  @media (prefers-reduced-motion: reduce) { .topbar .nb-item, .topbar .nb-item:hover { transition: none; transform: none; } }
  /* 여러 개 고르는 칩 (원장 지정 2026-10-19) — 안 고른 것은 흰 바탕 · 검은 테두리, 고른 것은 검은 칸. 미끄러지지 않아요 */
  .type-options.multi > .type-option { background: #fff; color: var(--text-primary); border: 1px solid var(--text-primary); padding: 5px 11px; }
  .type-options.multi > .type-option:hover { background: #fff; }
  .type-options.multi > .type-option.active { background: var(--point); color: #fff; }
  /* 상세의 '삭제' — 저장 · 비밀번호 초기화와 같은 줄, 같은 모양에 빨강 (원장 지정 2026-10-19 · 목록의 × 대신 · 가이드 0-6) */
  .btn-2nd.btn-del { color: #e53e3e; border-color: #e53e3e; }
  /* 1차 탭 줄 오른쪽 2차 메뉴 (원장 지정 2026-10-19 · 앱 아이패드 SecondSlot 과 같은 모양 — 세로선 0.5 · 높이 22 · 양옆 18) */
  /* 세로 가운데는 탭 **글자**에 맞춰요 (원장 지적 2026-10-24) — 탭 칸은 글자 위 6 · 아래 10 이라 칸 가운데에 두면
     2차 칩 글자가 1차 글자보다 3.7px 아래로 내려가 있었어요. 아래 여백으로 그만큼 올려요 (--tab-lift) */
  .tabs { --tab-lift: 6px; }
  .tabs .tab-sep { align-self: center; width: 0.5px; height: 22px; background: var(--line); margin: 0 18px var(--tab-lift); flex: none; }
  .tabs .tab-second { align-self: center; flex-wrap: nowrap; margin-bottom: var(--tab-lift); }
  .topbar-icon.active { background: var(--surface2); border-radius: 8px; }
  /* 중앙 팝업 (모션 가이드 8번) — 흰 바탕 · 모서리 10 · 덮개 검정 60% · 버튼 알약 */
  .dlg-back { position: fixed; inset: 0; z-index: 300; display: flex; align-items: center; justify-content: center; background: rgba(0,0,0,0); transition: background 750ms cubic-bezier(0.25, 0.1, 0.25, 1); }
  .dlg-back.open { background: rgba(0,0,0,0.6); }
  .dlg-back.closing { transition-duration: 300ms; }
  .dlg { width: min(440px, calc(100vw - 32px)); max-height: 80vh; overflow: auto; background: #fff; border-radius: 10px; padding: 24px; opacity: 0; transform: translateY(18px); transition: opacity 620ms cubic-bezier(0.25, 0.1, 0.25, 1), transform 620ms cubic-bezier(0.25, 0.1, 0.25, 1); }
  .dlg-back.open .dlg { opacity: 1; transform: none; }
  .dlg-back.closing .dlg { transition-duration: 200ms; }
  .dlg-title { font-size: 16px; font-weight: 700; color: var(--text-primary); margin-bottom: 14px; }
  .dlg-body .field-label { margin-top: 12px; }
  .dlg-body .field-label:first-child { margin-top: 0; }
  .dlg-msg { font-size: 12px; color: #e53e3e; min-height: 0; margin-top: 8px; }
  .dlg-msg:empty { display: none; }
  .dlg-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 20px; }
  .dlg-btn { padding: 8px 18px; border-radius: 999px; font-size: 13px; font-weight: 600; cursor: pointer; user-select: none; outline: none; }
  .dlg-cancel { background: var(--surface2); color: var(--text-primary); }
  .dlg-ok { background: var(--point); color: #fff; }
  .dlg-btn:focus-visible { outline: 1.5px solid var(--point); outline-offset: 3px; }
  @media (prefers-reduced-motion: reduce) { .dlg-back, .dlg { transition: none; } }
  .dlg-file { font-size: 13px; color: var(--text-primary); }
  .dlg-file small { color: var(--text-muted); margin-left: 6px; }
  /* 태그 색 동그라미 */
  .tag-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex: none; }
  /* 폴더 맵 (원장 지정 2026-10-19) — 왼쪽 → 오른쪽 나무 · 칸은 '고르는 칸' 규칙(흰 바탕 · 검은 테두리) · 지금 폴더는 검은 칸 */
  #mapView { overflow: auto; padding-bottom: 12px; }
  .fmap { position: relative; }
  .fmap-lines { position: absolute; left: 0; top: 0; overflow: visible; }
  .fmap-lines path { fill: none; stroke: #9a9a9a; stroke-width: 1; }
  .fmap-node { position: absolute; display: flex; align-items: center; gap: 6px; padding: 0 10px; border: 1px solid var(--text-primary); border-radius: 8px; background: #fff; color: var(--text-primary); font-size: 12px; font-weight: 600; cursor: pointer; user-select: none; }
  .fmap-node.on { background: var(--point); color: #fff; }
  /* 올리면 살짝 커져요 (원장 지정 2026-10-19 — 호버했다는 느낌) · 머리글 아이콘과 같은 220ms · EASE */
  .fmap-node { transition: transform 220ms cubic-bezier(0.25, 0.1, 0.25, 1); }
  .fmap-node:hover { transform: scale(1.06); z-index: 1; }
  @media (prefers-reduced-motion: reduce) { .fmap-node { transition: none; } .fmap-node:hover { transform: none; } }
  .fmap-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .fmap-count { font-size: 11px; font-weight: 400; opacity: 0.6; }
  /* 화면 위 1차 탭 (프로젝트 · 콘텐츠) — Points 의 [학생][주문] 과 같은 자리 */
  .tabs.page-tabs { margin: 16px calc(var(--pad-x) - 12px) 0; flex-shrink: 0; }
  /* 상담 예약 — 왼쪽 상담 신청 (원장 지정 2026-10-19) */
  .ask-box { padding: 24px calc(var(--pad-x) - 12px) 56px; }
  .ask-item { padding: 14px 12px; border-radius: 8px; cursor: pointer; }
  .ask-item:hover { background: var(--surface2); }
  .ask-item + .ask-item { margin-top: 6px; }
  .ask-top { display: flex; align-items: center; gap: 8px; margin-bottom: 2px; }
  .ask-state { margin-left: auto; font-size: 11px; color: var(--text-secondary); }
  .ask-item.is-new .ask-state { color: #C8323B; font-weight: 600; }
  .ask-msg { font-size: 12px; color: var(--text-primary); margin-top: 4px; line-height: 1.5; }
  /* 상담 달력의 요일 줄은 칸과 같은 7칸 격자 — 학습 스케줄 달력의 .cal-head(한 줄 flex)가 덮어써서 요일이 어긋났어요 (원장 지적 2026-10-19) */
  #cal > .cal-head, #cal > .cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); column-gap: 14px; }
  #cal > .cal-head { margin-bottom: 6px; }
  .topbar-logout { align-self: center; margin-right: 6px; font-size: 13px; font-weight: 600; color: #4a4a4a; cursor: pointer; user-select: none; }
  .topbar-logout:hover { color: var(--text-primary); }
  /* Folio 한도 칸 — 숫자 몇 자리라 짧게 (원장 지적 2026-10-19) */
  #tab-credit .form-row .form-field { flex: 0 0 180px; max-width: 180px; }
  /* 교재 구간 · 정답 줄 — 분량 · 자료 올리기 · × 가 이름에서 멀리 떨어지지 않게 (원장 지적 2026-10-19) */
  #dSections, #newSections, #keySections { max-width: 460px; }
  /* 아이콘 이름 — 아이콘 줄 오른쪽 끝 글자 (원장 지정 2026-10-19 · 말풍선 대신) */
  .topbar .nb-name { align-self: center; margin-left: 12px; font-size: 14px; font-weight: 600; color: #4a4a4a; white-space: nowrap; pointer-events: none; }
  /* 설정 아이콘과 화면 이름 사이 세로선 (원장 지정 2026-10-20 — 이름이 아이콘처럼 붙어 보였어요) · 탭 줄 세로선(.tab-sep)과 같은 모양 */
  .topbar .nb-name { border-left: 0.5px solid var(--line); padding-left: 14px; margin-left: 14px; line-height: 22px; }
  .topbar .navbar { align-items: center; }

  /* ── 2026-10-19 원장 지정 (네 번째) ── */
  /* 포인트색은 이제 **검정** (예전 청록 #0F4C5C 는 더 이상 포인트가 아니에요). 고른 칩 · 버튼 올림 · 칸 이름 등 --point 를 쓰는 곳이 모두 검정 */
  :root { --point: #0f0f0f; }
  .seating-board { --seat-teal: #0f0f0f; }
  .summary .lg:has(.dot.teal) { background: var(--surface2); color: var(--text-primary); }
  /* 주황(경고 · 확인 필요)은 모두 **빨강** — '동의 안 함' · 지각 · 부분 납부 · 바뀐 수업 · 재질문 등.
     단, 색으로 **종류를 가르는 곳**(상담 달력의 '학부모 상담' · 좌석의 '비정기 외출')은 빨강이 이미 다른 종류라 그대로 둬요 */
  .consent-no { color: #C8323B; }
  .consent-warn { color: #C8323B; background: #FDECEC; }
  .badge-late { color: #C8323B; background: #FDECEC; }
  .check-absent-irregular { color: #C8323B; }

  /* 칸 사이 여백은 **하나** — 칩 줄 · 버튼 줄 · 검색 줄 모두 8 (원장 지정 2026-10-19 — '공개 대상' 칩 사이와 '올리기 · 사진·파일' 사이가 같아야 해요) */
  .type-options, .action-row, .list-search.with-add, .filter-row, .linked-action-row { gap: 8px; }

  /* 고르기 칩의 미끄러지는 검은 칸 (common.js setupChipPills) — 칸이 깔린 줄은 칩마다 칠하지 않고 글자만 흰색 */
  .type-options { position: relative; }
  .chip-pill { position: absolute; left: 0; top: 0; border-radius: 8px; background: var(--point); pointer-events: none; z-index: 0; opacity: 0; }
  .type-options.has-pill > .type-option { position: relative; z-index: 1; }
  /* 바탕 · 글자색이 서서히 바뀌면, 멈추는 순간 검은 칸은 사라졌는데 고른 칩의 검은 바탕은 아직 덜 칠해져
     흰 글자가 흰 바탕에 묻혀 번쩍였어요 (원장 지적 2026-10-20 '선택된 후 깜빡거림'). 미끄러지는 줄은 바로 바꿔요 */
  .type-options.has-pill > .type-option { transition: none; }
  /* 미끄러지는 동안만 칩 바탕을 비워 알약이 보이게 — 멈추면 고른 칩이 제 검은 바탕을 가져요 (2026-10-19) */
  .type-options.pill-moving > .type-option { background: transparent; }
  .type-options.pill-moving > .type-option.active { color: #fff; }

/* 버튼 크기는 '활성 · 비활성' 칩과 같게 (원장 지정 2026-10-19 — 버튼이 칩보다 커서 '내려받기' 가 회차 칩 옆에서 튀었어요).
   글자 12 · 위아래 5 · 좌우 11 · 테두리 1 — 칩(.type-option)과 같은 값이에요 */
.btn-1st, .btn-2nd, .add-btn { display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; min-height: 28px; font-size: 12px; font-weight: 600; padding: 5px 11px; border-width: 1px; border-style: solid; }
.btn-1st { border-color: var(--point); }
.btn-2nd, .add-btn { border-color: var(--text-primary); }
.btn-2nd.btn-del { border-color: #e53e3e; }
.add-box { width: 28px; height: 28px; border-width: 1px; }

/* 질문 게시판 — Minor · Major 차이 한 줄 (버튼 줄 아래로 · 2026-10-24) */
#cActions { flex-wrap: wrap; }
#cActions > .btn-1st, #cActions > .btn-2nd { white-space: nowrap; }
.ai-bird-note { flex-basis: 100%; margin-top: 2px; }
/* 요청사항 칸 — 고른 AI 아래 한 줄 (선택 · 2026-10-24) */
#cActions > .btn-2nd.selected { background: var(--sidebar-active); }
.ai-req { flex-basis: 100%; display: flex; align-items: center; gap: 8px; }
.ai-req .field-input { flex: 1; min-width: 0; }

/* 목록 안 묶음 제목 (Solist Points › 상품 — 우리 학원 · Solist 공통 · 2026-10-24) */
.list-group-title { font-size: 11px; font-weight: 700; color: var(--text-muted); letter-spacing: 0.4px; padding: 6px var(--pad-x) 4px; }

/* 결제 › 청구서의 항목 고르기 — 작은 칩 (원장 지정 2026-10-24 · 여러 개 고르는 칩 모양 · 고른 것은 검은 칸) */
.item-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.item-chip { position: relative; display: inline-flex; align-items: baseline; gap: 6px; padding: 5px 11px; border: 1px solid var(--text-primary); border-radius: 8px; font-size: 12px; font-weight: 600; cursor: pointer; user-select: none; background: #fff; }
.item-chip input { position: absolute; opacity: 0; pointer-events: none; }
.item-chip b { font-weight: 500; font-size: 11px; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.item-chip:has(input:checked) { background: var(--text-primary); color: #fff; }
.item-chip:has(input:checked) b { color: rgba(255, 255, 255, 0.75); }
.item-chip:has(input:focus-visible) { outline: 2px solid var(--text-primary); outline-offset: 2px; }

/* 반 · 수업 · 장학 설명 — 이름 아래 한두 줄 (2026-10-24) */
.panel-desc { font-size: 13.5px; color: var(--text-secondary); line-height: 1.6; margin: 10px 0 4px; max-width: 64ch; white-space: pre-line; }

/* ── 설정 › Solist 이용 학생 (학생 수 과금 · 2026-10-24) ── */
.usage-head { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 14px; }
.usage-month { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
.usage-state { font-size: 11px; font-weight: 600; color: var(--text-secondary); background: var(--surface); border-radius: 6px; padding: 2px 8px; }
.usage-state.final { color: #fff; background: var(--text-primary); }
.usage-sum { display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap; margin-bottom: 10px; }
.usage-num { font-size: 32px; font-weight: 800; letter-spacing: -0.6px; font-variant-numeric: tabular-nums; }
.usage-unit { font-size: 14px; font-weight: 600; margin-left: 3px; }
.usage-src { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.usage-chip { font-size: 11.5px; color: var(--text-secondary); background: var(--surface); border-radius: 6px; padding: 3px 9px; }
.usage-chip b { color: var(--text-primary); margin-left: 3px; font-variant-numeric: tabular-nums; }
.usage-table { width: 100%; }
.usage-table th.name-cell, .usage-table td.name-cell { text-align: left; padding-left: 0; }
.op-flag { color: #C8323B; font-weight: 700; }

/* ── 전체 현황 — 한 화면 격자 (원장 지정 2026-10-24) ──
   요약 카드 = 옅은 회색 카드(--surface · 모서리 8 · 그림자 없음 · 태블릿 톤 카드 규칙). 3칸 → 1280 이하 2칸 → 760 이하 1칸 */
.dash-grid { flex: 1; overflow-y: auto; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; align-content: start; padding: var(--pad-top) var(--pad-x) 56px; }
.dash-card { background: var(--surface); border-radius: 8px; padding: 18px 20px 20px; min-width: 0; }
.dash-card[hidden] { display: none; }
.dash-card.span-2 { grid-column: span 2; }
.dash-card.span-3 { grid-column: 1 / -1; }
.dash-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; }
.dash-title { font-size: 15px; font-weight: 700; margin-right: auto; }
.dash-total { margin-left: 4px; color: #C8323B; font-variant-numeric: tabular-nums; }
.dash-note { font-size: 11px; color: var(--text-muted); }
.dash-link { font-size: 11.5px; font-weight: 600; color: var(--text-secondary); cursor: pointer; }
.dash-link:hover { color: var(--text-primary); }
.dash-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.dash-tile { background: #fff; border-radius: 8px; padding: 12px 14px; cursor: pointer; min-width: 0; }
.dash-tile:hover { outline: 1px solid var(--text-primary); }
.dash-tile-label { font-size: 11.5px; font-weight: 600; color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dash-num { font-size: 24px; font-weight: 800; letter-spacing: -0.4px; margin-top: 4px; font-variant-numeric: tabular-nums; color: var(--text-muted); }
.dash-num span { font-size: 12px; font-weight: 600; margin-left: 2px; }
.dash-tile.on .dash-num, .dash-num.big { color: var(--text-primary); }
.dash-num.big { font-size: 28px; margin: 4px 0 10px; }
.dash-sub { font-size: 11px; color: var(--text-muted); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dash-rows { display: flex; flex-direction: column; }
.dash-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 7px 0; font-size: 12.5px; color: var(--text-secondary); }
.dash-row[onclick] { cursor: pointer; }
.dash-row b { font-size: 14px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.dash-row.on b, #overview .dash-row b { color: var(--text-primary); }
.dash-line { display: flex; gap: 14px; padding: 8px 0; font-size: 12.5px; cursor: pointer; min-width: 0; }
.dash-line:hover .dash-text { text-decoration: underline; }
.dash-date { color: var(--text-muted); font-variant-numeric: tabular-nums; flex-shrink: 0; }
.dash-text { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dash-flag { font-size: 10.5px; color: #C8323B; margin-right: 6px; }
.dash-people { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 8px; }
.dash-person { background: #fff; border-radius: 8px; padding: 10px 12px; display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 8px; align-items: center; }
.dash-person-name { font-size: 13px; font-weight: 600; }
.dash-person .dash-sub { grid-column: 1; }
.dash-person .attend-badge { grid-column: 2; grid-row: 1 / span 2; }
.dash-empty { font-size: 12px; color: var(--text-muted); padding: 6px 0; }
@media (max-width: 1280px) {
  .dash-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .dash-card.span-2 { grid-column: 1 / -1; }
}
@media (max-width: 760px) {
  .dash-grid { grid-template-columns: minmax(0, 1fr); padding: 16px 16px 40px; }
  .dash-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ── 좁은 화면 (Codex 사용 점검 CUX-01 · 2026-10-19) ──
   공지 · 질문 목록이 528px 로 고정이고 오른쪽 칸(중요 공지 · 서식)도 고정이라, 아이패드 세로(820)에서
   가운데 상세가 0px 이 되어 제목 · 본문이 안 보였어요 (가로 1180 에서도 제목이 36px). 폰(390)은 화면 밖으로 밀렸어요.
   칸을 없애지 않고 **자리만** 바꿔요 — 넓은 PC(1281px~)는 예전 그대로예요. */

/* 제목 줄 — 제목 묶음이 남는 폭을 다 가져요 (예전엔 제목과 .spacer 가 flex:1 로 폭을 반씩 나눠 제목이 눌렸어요) */
.panel-head > :first-child { flex: 1 1 auto; min-width: 0; }
.panel-head .spacer { flex: 0 0 0; }

@media (max-width: 1280px) {
  /* 넓은 목록은 화면의 38% 까지만 (최대 528 · 최소 240) */
  .list-panel.wide-list { width: 38%; max-width: 528px; min-width: 240px; }
  /* 공지 3칸 → 2칸: 목록 | 상세, 오른쪽 칸(중요 공지 · 서식)은 상세 **아래**로 */
  .body-wrap:has(> .notice-important) { display: grid; grid-template-columns: minmax(240px, 38%) minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto; }
  .body-wrap:has(> .notice-important) > .list-panel { grid-column: 1; grid-row: 1 / span 2; width: auto; min-width: 0; }
  .body-wrap:has(> .notice-important) > .detail-panel { grid-column: 2; grid-row: 1; min-width: 0; }
  .body-wrap > .notice-important { grid-column: 2; grid-row: 2; width: auto; max-height: 40vh; padding: 16px 24px 24px; border-top: 0.5px solid var(--line); }
  /* 머리글 아이콘 줄 — 넘치면 옆으로 밀어서 봐요 (로그아웃 · 채팅 · 알림과 겹치지 않게). 이름 글자는 숨겨요 */
  .topbar .navbar { overflow: hidden; }
  .topbar .nb-menu { overflow-x: auto; overflow-y: hidden; padding-bottom: 6px; margin-bottom: -6px; scrollbar-width: none; }
  .topbar .nb-menu::-webkit-scrollbar { display: none; }
  .topbar .nb-name { display: none; }
}

@media (max-width: 760px) {
  :root { --ui-zoom: 1; }
  /* 폰 — 위아래로 쌓아요: 목록(높이 40% 까지 · 안에서 스크롤) → 상세 → (공지) 오른쪽 칸 */
  .body-wrap { flex-direction: column; overflow-y: auto; }
  .body-wrap > .list-panel, .list-panel.wide-list { width: 100%; max-width: none; min-width: 0; max-height: 40vh; flex-shrink: 0; border-right: none; border-bottom: 0.5px solid var(--line); padding-top: 12px; }
  .body-wrap > .detail-panel { flex: 1 0 auto; min-width: 0; overflow: visible; }
  .body-wrap:has(> .notice-important) { display: flex; }
  .body-wrap > .notice-important { max-height: none; }
  .topbar-logout { margin-right: 2px; }
  /* 질문 과목 탭 — 두 줄로 넘어가면 밑줄이 엉뚱한 줄에 붙어요. 한 줄로 두고 옆으로 밀어요 */
  .qna-filter .section-tabs.tabs { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .qna-filter .section-tabs.tabs::-webkit-scrollbar { display: none; }
  .qna-filter .section-tabs.tabs .tab { flex-shrink: 0; }
  /* 예전 폰용 서랍 규칙(767px 이하 · 위쪽)이 머리글 아이콘 줄을 화면 밖으로 숨겼어요 — 머리글 안에서는 그대로 한 줄 */
  .topbar .navbar { position: static; transform: none; visibility: visible; max-width: none; padding: 0; top: auto; bottom: auto; left: auto; }
  .topbar .nb-item { width: 34px; padding: 0; justify-content: center; }
  .topbar .nb-label { display: none; }
}

/* 입력칸 + 바로 옆 '+' — 칸 높이 가운데 · 10px 간격 (출석부 › 출석 확인 › 시간 추가 · 2026-10-24) */
.field-add { display: flex; align-items: center; gap: 10px; }
.field-add > .field-input { flex: 1; min-width: 0; }
.field-add > .add-box { flex-shrink: 0; }
.field-add > .field-textarea { flex: 1; min-width: 0; line-height: normal; } /* 한 줄일 때 옆 입력칸과 같은 높이 */
.field-add > .btn-2nd { flex-shrink: 0; white-space: nowrap; }
.brief-sub .brief-link { margin-left: 8px; text-decoration: underline; }
.shelf-share-warn { color: #C8323B; font-weight: 600; margin: -4px 0 12px; }
/* 청구 › 학생 고르기 줄 — 마우스를 올리면 다른 목록처럼 줄 전체에 옅은 회색 칸 (원장 지정 2026-10-24).
   체크 칸만 진해지던 것은 이 줄에선 끄요 (줄이 반응하니 겹쳐요) */
.linked-item.pick-row { cursor: pointer; border-radius: 8px; padding: 12px; margin: 0 -12px; transition: background 0.1s; }
.linked-item.pick-row:hover { background: var(--surface); }
.linked-item.pick-row input[type="checkbox"]:not(:checked):hover { border-color: #d0d0d0; }
/* 머리글 학원 전환 — 여러 학원을 운영하는 원장만 (2026-10-26) · 로그아웃 글자와 같은 크기, 목록은 .picker-list 와 같은 칸 */
.academy-switch { position: relative; align-self: center; margin-right: 16px; }
.academy-switch-now { display: inline-flex; align-items: center; gap: 4px; font-size: 13px; font-weight: 600; color: var(--text-primary); cursor: pointer; user-select: none; }
.academy-switch-now svg { display: block; }
.academy-switch-now:hover { opacity: 0.6; }
.academy-switch-list { position: absolute; top: calc(100% + 8px); right: 0; min-width: 200px; z-index: 150; background: #fff; border: 0.5px solid var(--line); border-radius: 10px; padding: 6px; }
/* 로고 (원장 작성 2026-10-26 · docs/brand) — 높이만 정하면 비율대로 */
.brand-logo { display: block; height: 26px; width: auto; }
