/*
 * 자가진단 — 학생 화면 공용 모양 (셸 + 부품)
 *
 * ## 교수 화면과 «다른» 파일이다
 *
 * 규칙 13-5 ④가 자가진단의 경로를 평가 채점의 그것과 분리하라고 정한다.
 * 하나를 고치다 다른 하나가 딸려 바뀌는 일이 없도록 파일부터 나눈다.
 *
 * ## 2026-09-26 — 콘솔 문법으로 다시 그렸다 (허준구 결정)
 *
 * 처음 판(크림 바탕 · 갈색 강조 · 세로 태블릿 · 하단 탭바)과 `DOCS/UIUX` 목업(파랑 · 카드)이
 * 둘 다 «문서»처럼 보여 버렸다. 관리 콘솔의 문법으로 바꿨다 —
 * 남색 상단 바 · 왼쪽 메뉴 · 머리 있는 상자 · 표 · 상태 아이콘 · 파란 알약 단추.
 * 기준 화면은 **가로 태블릿·데스크톱(1180px)** 이고, 세로 태블릿과 휴대폰은 메뉴가 위로 접힌다.
 *
 * 셸이 화면에게 요구하는 계약(`<body>` 의 data 속성 넷 · `<main>`)은 그대로다 (`shell.js`).
 *
 * ## 2026-09-29 — 문법은 두고 «결»을 고쳤다
 *
 * 이 손질에서는 위 문법(상단 바 · 왼쪽 메뉴 · 머리 있는 상자 · 표 · 상태 아이콘 · 알약 단추)을 하나도 안 바꿨다.
 * (같은 날 아래 「둘째」에서 둘이 바뀐다 — 메뉴의 색과 단추의 모양.)
 * 바꾼 것은 그 아래의 결이다. 잣대는 Hallmark(Nutlope/hallmark · MIT)의 목록을 빌렸다.
 *
 *   · 순백 · 토큰 밖의 색을 없앴다 — 색은 전부 아래 `:root` 의 이름으로만 쓴다
 *   · 상자는 겹그림자와 큰 모서리 대신 «가는 줄 하나»로 선다
 *   · 옆구리에 굵은 색 줄을 댄 상자를 없앴다 · 상자 안의 상자에는 테두리를 또 긋지 않는다
 *   · 단추와 입력칸이 높이를 같이 쓴다. 손가락으로 누르는 기기에서는 44px 다
 *   · 눌렀을 때 · 자판으로 닿았을 때 · 못 누를 때의 모양을 전부 적었다. 닿은 표시는 곧바로 뜬다
 *   · 크기와 간격은 아래 척도에서만 고른다 (12.5 · 13.5 · 14.5 같은 사잇값을 없앴다)
 *   · 강조색은 «짚는 데»만 쓴다 — 고지 상자의 굵은 파란 테두리를 걷었다
 *
 * ## 2026-09-29 (둘째) — 짙은 옆면 (ParkTaeKyun 결정)
 *
 * 위의 손질로는 「바뀐 줄 모르겠다」. 시안 둘(짙은 옆면 · 먹)을 그려 보이고 앞의 것을 골랐다.
 * 여기서는 2026-09-26 의 문법 가운데 «둘»이 바뀐다 — 숨기지 않고 적는다.
 *
 *   · 왼쪽 메뉴가 흰 바탕에서 «상단 바와 같은 남색»으로 — 상단 바와 메뉴가 한 덩이(ㄱ자)가 된다
 *   · 단추가 알약에서 «둥근 네모»로
 *
 * 그대로인 것 — 남색 상단 바 · 머리 있는 상자 · 표 · 상태 아이콘 · 강조색(남청).
 * 곁들여 제목을 키우고(24 → 30), 화면 머리 아래에 줄을 긋고, 상자 머리에 옅은 바탕을 깔았다.
 *
 * ## 2026-09-29 (셋째) — 누가 봐도 달라지게 (ParkTaeKyun 결정)
 *
 * 둘째까지는 색과 모서리를 바꿨을 뿐 «뼈대»가 같았다. 여기서 뼈대에 손을 댄다.
 *
 *   · 화면 머리가 «흰 띠»가 된다 — 제목이 첫 줄, 설명이 그 아래. 회색 본문 위에 얹힌다
 *   · 상단 바를 키우고 제품 표시를 단다. 제품 이름의 폭이 왼쪽 메뉴의 폭과 같다
 *   · 메뉴에 그림을 달고, 「지금 여기」를 옆구리 줄이 아니라 «안으로 들인 덩이»로 짚는다
 *   · 상태는 색 글씨가 아니라 «꼬리표»로
 *   · 짙은 상자(`.box.dark`)와 차례(`.steps`) — 홈의 「지금 하실 일」
 *   · 결과·채점 화면 맨 위의 고지는 상자가 아니라 «화면 폭의 띠»
 *
 * ## 2026-09-29 (넷째) — 쓰기도 나아지게 (ParkTaeKyun 「맘에 들어 · 좀 더」)
 *
 *   · 결과 화면 — 곁의 목록을 누르면 그 논점으로 간다. 읽고 있는 논점이 목록에서 짚인다
 *   · 접히는 칸에 «접힌다는 표시»(꺾쇠)를 달았다. 그전에는 접히는지 알 길이 없었다
 *   · 상단 바의 뒤로 · 밝기에 그림
 *   · 손을 올렸을 때 색이 «짧게» 바뀐다 (0.12초). 닿은 표시(바깥 줄)는 여전히 곧바로 뜬다
 *   · 되살릴 수 없는 일을 하는 상자(`.box.danger`)는 머리가 붉다
 *   · 작은 꼬리표(`.tag`) — 과목처럼 «가르는 말»
 *
 * 색을 16진수로 둔 것은 일부러다. 기준으로 삼은 목록은 oklch 를 권하나, 그 표기를 못 읽는
 * 오래된 태블릿에서는 색이 통째로 빠진다. 값은 기준색(남청) 쪽으로 옅게 물들여 골랐고
 * 글과 바탕의 대비는 밝은 쪽 · 어두운 쪽 33쌍씩 재어 전부 기준을 넘겼다.
 *
 * ## 점수를 앞세우지 아니한다
 *
 * 원칙 7 ②가 「학생에게 필요한 것은 절대 점수가 아니라 «내가 어느 논점을 빠뜨렸나»」라고
 * 적었다. 그래서 총점을 큰 글씨로 맨 위에 두지 않는다. 그 배치가 곧 제품이 무엇을 말하려는지다.
 */

:root {
  /* ── 바탕과 글 — 순백도 순흑도 아니다. 전부 남청 쪽으로 옅게 물들였다 ── */
  --bg: #eef0f4;
  --panel: #fbfcfd;
  --panel-2: #f3f5f8;      /* 상자 «안»의 덩이 — 테두리 대신 바탕으로 가른다 */
  --line: #bfc5ce;
  --line2: #dfe3e9;
  --control: #7f8a9a;      /* 입력칸 · 스위치의 테두리. 바탕과 3:1 을 넘긴다 */
  --ink: #141a22;
  --ink2: #3a4452;
  --muted: #596474;

  /* ── 상단 바 ── */
  --nav: #1d2836;
  --nav-ink: #f3f5f8;
  --nav-line: #3a4656;
  --nav-dim: #c5ccd6;
  --nav-mute: #9aa6b5;     /* 메뉴의 머리 글 — 메뉴 글보다 한 걸음 물러난다 */
  --nav-on: #7db6f0;       /* 남색 «위»의 강조 — 켜진 메뉴의 표시 줄 */
  --bar-h: 48px;           /* 상단 바의 높이. 붙박는 것들이 이 아래에서 멈춘다 */

  /* ── 강조 하나 — 남청. 짚는 데만 쓴다 ── */
  --accent: #0b5cad;
  --accent-bg: #edf3fa;
  --accent-ink: #083f78;   /* 강조색의 짙은 쪽 — 주 단추에 손을 올렸을 때 */
  --on-accent: #fbfcfd;    /* 강조색 «위»의 글 */
  --focus: #0b5cad;        /* 자판으로 닿은 표시 */

  /* ── 판정색 — 더 볼 곳 · 짚은 곳 · 일부 ── */
  --miss: #c21d1d;
  --miss-bg: #fdf3f2;
  --hit: #0a7430;
  --hit-bg: #f0f8f1;
  --part: #7d5904;
  --part-bg: #fbf6e3;

  /* ── 내부 시범 띠 ── */
  --trial-bg: #fbf6e3;
  --trial-line: #e3d5a3;
  --trial-ink: #564008;
  --trial-dim: #6e5818;

  /* ── 글꼴 — Pretendard 를 «싣는다» (아래 `@font-face`). 못 받은 기기는 뒤의 것으로 그린다.
        제목과 본문의 자리는 나눠 두되 같은 글꼴을 가리킨다 — 굵기로 가른다 ── */
  --font-body: "Pretendard Variable", "Pretendard", "Noto Sans KR", "Apple SD Gothic Neo",
    "Malgun Gothic", system-ui, -apple-system, sans-serif;
  --font-display: var(--font-body);

  /* ── 굵기 — 셋에서만 고른다. 가변 글꼴이라 사잇값도 그려지지만 쓰지 않는다 ── */
  --w-body: 400;
  --w-strong: 600;         /* 단추 · 표 머리 · 탭 — 누르거나 가르는 글 */
  --w-head: 700;           /* 제목 · 본문 안의 강조 */

  /* ── 글자 크기 — 여기 적힌 것에서만 고른다 ── */
  --t-glyph: 10px;         /* 상태 아이콘 안의 글자 하나 */
  --t-xs: 12px;
  --t-sm: 13px;
  --t-md: 14px;
  --t-read: 15px;          /* 길게 읽는 글 — 문제 · 답안 */
  --t-lg: 16px;
  --t-xl: 18px;
  --t-2xl: 24px;
  --t-3xl: 30px;           /* 화면의 제목 */
  --t-4xl: 40px;           /* 결과 화면의 「더 볼 논점 수」 하나 */

  /* ── 간격 — 4 의 배수. 이 여덟에서만 고른다 ── */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 20px;
  --sp-6: 24px;
  --sp-8: 32px;
  --sp-10: 40px;

  /* ── 모서리 · 깊이 ── */
  --r: 10px;               /* 상자 */
  --r2: 6px;               /* 입력칸 · 상자 안의 덩이 */
  --r-btn: 8px;            /* 단추 — 둥근 네모 */
  --r-pill: 999px;         /* 스위치 · 막대 */
  --shadow: none;          /* 상자는 줄로 선다. 그림자를 쓰지 않는다 */

  /* ── 누르는 것의 높이 — 단추와 입력칸이 같이 쓴다 ── */
  --ctl: 36px;

  /* ── 겹치는 차례 — 숫자를 그때그때 짓지 않는다 ── */
  --z-menu: 10;
  --z-bar: 200;

  --rail: 236px;
}

/* 손가락으로 누르는 기기 — 44px 아래로는 잘못 누른다 */
@media (pointer: coarse) {
  :root { --ctl: 44px; }
}

/*
 * ── 글꼴 파일 ─────────────────────────────────────────────────────
 *
 * Pretendard 1.3.9 · 가변 글꼴 한 파일 (2026-09-29 · 사용자 결정).
 * 이용 조건은 SIL Open Font License 1.1 이고 그 글을 `fonts/` 에 함께 두었다 — 같이 있어야 한다.
 *
 * ★ 글꼴을 «이 화면을 내보내는 곳»에서 같이 내보낸다. 바깥의 글꼴 창고를 부르지 않는다.
 *   부르면 학생이 화면을 열 때마다 그 창고에 접속 기록이 남는다 (규칙 13-5 ③ 의 취지 · 원칙 25 ②).
 *   시험이 이 폴더의 모양 파일에서 바깥 주소를 막고 있기도 하다.
 *
 * 받는 동안에는 기기의 글꼴로 먼저 그리고, 다 받으면 바꾼다 (`swap`). 글이 안 보이는 때를 두지 않는다.
 */
@font-face {
  font-family: "Pretendard Variable";
  font-weight: 45 920;
  font-style: normal;
  font-display: swap;
  src: url("/fonts/PretendardVariable.woff2") format("woff2-variations");
}

* { box-sizing: border-box; }

/*
 * ★ `hidden` 은 어떤 `display` 규칙보다 세야 한다.
 *
 * 브라우저 기본 규칙은 `[hidden] { display: none }` 인데, 그건 **제작자 규칙에 진다.**
 * 그래서 `.actionbar { display: flex }` 같은 줄 하나가 `hidden` 을 통째로 무력화한다.
 * 실제로 세 곳이 그렇게 «숨긴 줄 알고» 보이고 있었다 (2026-09-23 에 브라우저로 확인).
 * `!important` 를 쓰는 유일한 자리다 — 이기라고 있는 규칙이다.
 */
[hidden] { display: none !important; }

/* 가로로 밀리는 화면을 두지 않는다. `hidden` 이 아니라 `clip` — 붙박인 상단 바가 그대로 산다 */
html { background: var(--bg); overflow-x: clip; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: var(--t-md)/1.55 var(--font-body);
  overflow-x: clip;
  /* 우리말은 «낱말»에서 줄을 바꾼다. 그냥 두면 브라우저가 글자마다 끊어 「이것만으 / 로」가 된다.
     띄어쓰기 없는 긴 글(주소 · 코드)은 그래도 넘치지 않게 끊는다. */
  word-break: keep-all;
  overflow-wrap: anywhere;
}

a { color: var(--accent); text-decoration: none; }
b { font-weight: var(--w-head); }

/* 자판으로 닿은 표시 — «곧바로» 뜬다. 서서히 나타나게 하지 않는다 */
a:focus-visible, button:focus-visible, summary:focus-visible, label.btn:focus-visible {
  outline: 2px solid var(--focus); outline-offset: 2px;
}

/* ── 글 계층 ─────────────────────────────────────────── */

h1 {
  margin: 0; font-family: var(--font-display);
  font-size: var(--t-3xl); font-weight: var(--w-head); letter-spacing: -0.02em; line-height: 1.2;
  text-wrap: balance;
}
h2 { margin: var(--sp-6) 0 var(--sp-2); font-family: var(--font-display); font-size: var(--t-xl); font-weight: var(--w-head); }
h3 { margin: 0 0 var(--sp-1); font-size: var(--t-md); font-weight: var(--w-head); }
.eyebrow { margin: 0 0 var(--sp-1); font-size: var(--t-xs); color: var(--muted); }
.lead { margin: 0 0 var(--sp-3); color: var(--ink2); font-size: var(--t-md); max-width: 68ch; text-wrap: pretty; }
.sub { margin: 0 0 var(--sp-2); color: var(--muted); font-size: var(--t-sm); text-wrap: pretty; }
.muted { color: var(--muted); }

/* 화면 머리 — 흰 띠. 회색 본문 위에 얹혀 화면의 첫 줄을 이룬다.
   제목이 첫 줄, 설명이 그 아래, 동작은 오른끝에 세로 가운데.
   본문의 안 여백을 거슬러 올라가 상단 바 바로 아래에 붙는다 (`--page-top` · `--page-x`). */
.page-head, .g-head {
  position: relative;
  margin: calc(-1 * var(--page-top)) calc(-1 * var(--page-x)) var(--sp-6);
  padding: var(--sp-6) var(--page-x) var(--sp-5);
  background: var(--panel); border-bottom: 1px solid var(--line2);
}
/* 본문에는 너비의 끝이 있으나 띠는 화면 오른끝까지 간다 */
.page-head::after, .g-head::after {
  content: ""; position: absolute; top: 0; bottom: -1px; left: 100%; width: 100vw;
  background: var(--panel); border-bottom: 1px solid var(--line2);
}
.page-head {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--sp-1) var(--sp-5); align-items: center;
}
.page-head > h1 { grid-column: 1; }
.page-head .desc { grid-column: 1; color: var(--muted); font-size: var(--t-md); max-width: 72ch; text-wrap: pretty; }
.page-head .actionbar { grid-column: 2; grid-row: 1 / span 2; padding: 0; }

/* ── 고지 — 조용한 덩이. 맨 위에 두는 것은 화면의 몫 ───────
   굵은 색 테두리로 소리치지 않는다. 첫 줄의 굵은 글씨와 작은 네모 하나가 짚는다. */

.notice, .alert {
  display: flex; gap: var(--sp-3); align-items: flex-start;
  padding: var(--sp-3) var(--sp-4); margin: 0 0 var(--sp-4);
  border: 1px solid var(--line2); border-radius: var(--r2);
  background: var(--panel-2); color: var(--ink);
  font-size: var(--t-md);
}
.notice::before, .alert::before {
  content: ""; flex: none;
  width: 8px; height: 8px; margin-top: 7px;
  background: var(--accent);
}
.notice strong { display: block; }
.notice span { display: block; color: var(--ink2); }
.notice > * { min-width: 0; }
.notice.warn { border-color: var(--trial-line); background: var(--part-bg); }
.notice.warn::before { background: var(--part); }

/* 상자 «안»의 고지 — 상자 안에 상자를 또 그리지 않는다. 바탕만으로 가른다 */
.box .notice, .stub .notice, .card .notice { border-color: transparent; }

/* 결과·채점 화면 맨 위의 고지 — 상자가 아니라 «화면 폭의 띠»다. 상단 바 바로 아래에 붙는다.
   띠 셋이 차례로 선다 — 내부 시범(누런) · 이 고지(옅은 남청) · 화면 머리(흰). */
body > .notice {
  margin: 0; padding: var(--sp-3) var(--page-x);
  border: 0; border-bottom: 1px solid var(--line2); border-radius: 0;
  background: var(--accent-bg);
}
body > .notice strong { display: inline; margin-right: var(--sp-2); }
body > .notice span { display: inline; }
.shell.has-tabbar > .notice { margin-left: var(--rail); }

/* ── 상자 — 머리 있는 칸. 가는 줄 하나로 선다 ─────────── */

.box, .stub, .card {
  background: var(--panel);
  border: 1px solid var(--line2);
  border-radius: var(--r);
  box-shadow: var(--shadow);
  margin: 0 0 var(--sp-5);
  padding: var(--sp-4) var(--sp-5);
  color: var(--ink);
}
.box > header, .stub > header, .card > header {
  display: flex; align-items: baseline; gap: var(--sp-1) var(--sp-3); flex-wrap: wrap;
  margin: calc(-1 * var(--sp-4)) calc(-1 * var(--sp-5)) var(--sp-4);
  padding: var(--sp-3) var(--sp-5);
  border-bottom: 1px solid var(--line2);
  /* 머리에 옅은 바탕 — 상자의 둥근 모서리를 따라간다 (줄 두께만큼 안쪽이라 1px 작다) */
  background: var(--panel-2);
  border-radius: calc(var(--r) - 1px) calc(var(--r) - 1px) 0 0;
}
.box > header h2, .stub > header h2, .card > header h2,
.box > header h3, .stub > header h3, .card > header h3 {
  margin: 0; font-size: var(--t-md); font-weight: var(--w-head); letter-spacing: .01em; white-space: nowrap;
}
.box > header .cnt { color: var(--muted); font-weight: var(--w-body); font-size: var(--t-md); font-variant-numeric: tabular-nums; }
.box > header .sub, .stub > header .sub { margin: 0; flex-basis: 100%; }
.box > header .actionbar, .stub > header .actionbar { margin-left: auto; padding: 0; align-self: center; }
.box > header p { margin: 0; }

.stub h2:first-child, .card h2:first-child { margin-top: 0; }
.stub p { margin: 0 0 var(--sp-2); }
.stub p:last-child { margin-bottom: 0; }
.stub ul { margin: 0; padding-left: var(--sp-5); color: var(--ink2); }
.stub li { margin-bottom: var(--sp-1); }
.stub code { font-size: var(--t-sm); color: var(--accent); }

/* 카드 머리 — 이름은 왼쪽, «그 카드의» 동작은 그 옆 */
.shell .stub-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-2) var(--sp-4); flex-wrap: wrap; margin-bottom: var(--sp-2);
}
.shell .stub-head > div { flex: 1 1 15em; min-width: 0; }
.shell .stub-head > div > * { margin: 0; }
.shell .stub-head > .btn { flex: 0 0 auto; }

/* ── 값 묶음 (이름 위 · 값 아래) ─────────────────────── */

.kv { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--sp-4) var(--sp-6); }
.kv .k { font-size: var(--t-xs); color: var(--muted); margin-bottom: var(--sp-1); }
.kv .v { font-size: var(--t-md); }
.kv .v.big { font-size: var(--t-2xl); font-weight: var(--w-head); font-variant-numeric: tabular-nums; }
.kv .v.big small { font-size: var(--t-md); font-weight: var(--w-body); color: var(--muted); }
.kv .v.miss { color: var(--miss); }

/* ── 상태 — 아이콘 + 한 낱말 ─────────────────────────── */

/* 색 글씨로만 말하지 않는다 — 옅은 바탕을 깐 꼬리표 하나로 묶는다. 아이콘과 낱말이 함께 있어
   색을 못 가리는 눈에도 뜻이 남는다. */
.st {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-1) var(--sp-3) var(--sp-1) var(--sp-2); border-radius: var(--r-pill);
  font-size: var(--t-sm); font-weight: var(--w-strong); line-height: 1.3; white-space: nowrap;
  background: var(--panel-2); color: var(--muted);
}
.st::before {
  content: ""; width: 14px; height: 14px; border-radius: 50%; flex: none;
  color: var(--on-accent); font-size: var(--t-glyph); font-weight: var(--w-head); line-height: 14px; text-align: center;
}
.st.ok   { color: var(--hit); background: var(--hit-bg); }       .st.ok::before   { background: var(--hit); content: "✓"; }
.st.miss { color: var(--miss); background: var(--miss-bg); }     .st.miss::before { background: var(--miss); content: "!"; }
.st.part { color: var(--part); background: var(--part-bg); }     .st.part::before { background: var(--part); content: "–"; }
.st.info { color: var(--accent); background: var(--accent-bg); } .st.info::before { background: var(--accent); content: "i"; }
.st.none { color: var(--muted); }                                .st.none::before { background: var(--line); }

/* ── 되살릴 수 없는 일을 하는 상자 — 머리가 붉다 ───────── */

.box.danger { border-color: var(--miss); }
.box.danger > header { background: var(--miss-bg); border-bottom-color: var(--miss); }
.box.danger > header h2 { color: var(--miss); }

/* ── 작은 꼬리표 — 과목처럼 «가르는 말». 상태(`.st`)와 달리 색이 없다 ─── */

.tag {
  display: inline-block; padding: 2px var(--sp-2); border-radius: var(--r2);
  border: 1px solid var(--line2); background: var(--panel-2); color: var(--ink2);
  font-size: var(--t-xs); font-weight: var(--w-strong); line-height: 1.4; white-space: nowrap;
}

/* ── 짙은 상자 — 화면에서 «하나만» 쓴다. 지금 할 일을 짚는 자리 ───────
   상단 바 · 메뉴와 같은 남색이다. 안의 글과 단추는 «남색 위»의 이름을 쓴다. */

.box.dark { background: var(--nav); border-color: var(--nav); color: var(--nav-ink); }
.box.dark > header { background: transparent; border-bottom-color: var(--nav-line); }
.box.dark .lead { color: var(--nav-dim); }
.box.dark .lead b { color: var(--nav-ink); }
.box.dark .btn { background: transparent; border-color: var(--nav-mute); color: var(--nav-ink); }
.box.dark .btn.primary { background: var(--nav-on); border-color: var(--nav-on); color: var(--nav); }
.box.dark .btn:active { background: var(--nav-line); }
.box.dark .btn.primary:active { background: var(--nav-ink); border-color: var(--nav-ink); }
.box.dark a:focus-visible, .box.dark button:focus-visible { outline-color: var(--nav-ink); }

/* ── 차례 — 번호는 «순서가 있을 때만» 단다 ─────────────────
   칸마다 상자를 두르지 않는다. 번호와 그것을 잇는 줄 하나가 순서를 말한다. */

.steps {
  list-style: none; counter-reset: step;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--sp-5);
  margin: var(--sp-5) 0 var(--sp-2); padding: 0;
}
.steps li { counter-increment: step; position: relative; padding-top: var(--sp-10); min-width: 0; }
.steps li::before {
  content: counter(step);
  position: absolute; top: 0; left: 0; width: 28px; height: 28px; border-radius: 50%;
  display: grid; place-items: center;
  border: 1px solid var(--nav-mute); color: var(--nav-dim);
  font-size: var(--t-sm); font-weight: var(--w-strong); font-variant-numeric: tabular-nums;
}
.steps li::after {
  content: ""; position: absolute; top: 14px; left: 36px; right: calc(-1 * var(--sp-5) + 8px);
  height: 1px; background: var(--nav-line);
}
.steps li:last-child::after { display: none; }
/* 첫 칸이 «여기서 시작»이다 */
.steps li:first-child::before { background: var(--nav-on); border-color: var(--nav-on); color: var(--nav); }
.steps b { display: block; font-weight: var(--w-strong); }
.steps span { display: block; margin-top: var(--sp-1); font-size: var(--t-sm); color: var(--nav-dim); }

/* ── 표 ──────────────────────────────────────────────── */

table { width: 100%; border-collapse: collapse; font-size: var(--t-md); }
th {
  text-align: left; font-weight: var(--w-strong); color: var(--muted);
  padding: var(--sp-2) var(--sp-3); border-bottom: 1px solid var(--line); font-size: var(--t-xs);
}
td { padding: var(--sp-3); border-bottom: 1px solid var(--line2); vertical-align: middle; transition: background-color .12s ease-out; }
tr:last-child td { border-bottom: 0; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
td.act { text-align: right; white-space: nowrap; }
.box > table, .stub > table {
  margin: 0 calc(-1 * var(--sp-5)) calc(-1 * var(--sp-4));
  width: calc(100% + 2 * var(--sp-5));
}
.box > header + table { margin-top: calc(-1 * var(--sp-4)); }
/* 표 «뒤»에 무엇이 더 오면 아래로 당기지 않는다 — 당기면 뒤에 오는 단추 줄이 마지막 줄을 덮는다 */
.box > table:not(:last-child), .stub > table:not(:last-child) { margin-bottom: 0; }
/* 표가 상자의 옆 줄에 붙으므로, 첫 칸과 끝 칸은 상자의 안 여백만큼 들인다 */
.box > table th:first-child, .box > table td:first-child { padding-left: var(--sp-5); }
.box > table th:last-child, .box > table td:last-child { padding-right: var(--sp-5); }

/* ── 탭 ──────────────────────────────────────────────── */

.tabs { display: flex; border-bottom: 1px solid var(--line); margin: 0 0 var(--sp-4); }
.tabs a {
  padding: var(--sp-2) var(--sp-4); color: var(--ink2); font-weight: var(--w-strong);
  border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap;
  transition: color .12s ease-out, border-color .12s ease-out;
}
.tabs a.on { color: var(--accent); border-bottom-color: var(--accent); }

/* ── 입력 ────────────────────────────────────────────── */

/* 16px 미만이면 iOS 사파리가 입력할 때 화면을 확대한다. 입력칸만 16px 로 고정한다. */
.shell input, .shell textarea, .shell select { font: inherit; font-size: var(--t-lg); }
.shell button { font: inherit; }

label { display: block; font-weight: var(--w-strong); font-size: var(--t-md); margin-bottom: var(--sp-1); }

/* 테두리 굵기는 어느 상태에서도 1px 이다 — 굵기가 바뀌면 글이 밀린다.
   닿은 표시는 테두리가 아니라 바깥 줄(outline)로 그리고, 자리는 미리 비워 둔다. */
input[type="text"], textarea, .editor {
  width: 100%; border: 1px solid var(--control); border-radius: var(--r2);
  padding: var(--sp-2) var(--sp-3); background: var(--panel); color: var(--ink);
  outline: 2px solid transparent; outline-offset: 1px;
}
input[type="text"] { height: var(--ctl); }
input:focus-visible, textarea:focus-visible, .editor:focus-visible {
  outline-color: var(--focus); border-color: var(--accent);
}
input:disabled, textarea:disabled { opacity: .55; cursor: not-allowed; }

/* ── 단추 — 둥근 네모 (2026-09-29 · 알약에서 바꿨다) ──── */

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--ctl); padding: 0 var(--sp-5); border-radius: var(--r-btn);
  border: 1px solid var(--accent); background: var(--panel); color: var(--accent);
  font: inherit; font-weight: var(--w-strong); font-size: var(--t-md); line-height: 1;
  text-decoration: none; cursor: pointer; white-space: nowrap;
  /* 바뀌는 것을 «이름으로» 적는다. 전부(all)를 걸지 않는다 — 닿은 표시가 서서히 뜨게 된다 */
  transition: background-color .12s ease-out, border-color .12s ease-out, color .12s ease-out;
}
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn.danger { border-color: var(--miss); color: var(--miss); }
.btn.plain { border-color: transparent; background: transparent; }

/* 누르는 동안 */
.btn:active { background: var(--accent-bg); }
.btn.primary:active { background: var(--accent-ink); border-color: var(--accent-ink); }
.btn.danger:active { background: var(--miss-bg); }

/* 못 누를 때 — 흐리게만 하지 않는다. 손 모양도 바꾼다 */
.btn:disabled, .btn[aria-disabled="true"] { opacity: .55; cursor: not-allowed; }

/* 동작 줄 — 단추를 오른쪽에 모은다 */
.actionbar { display: flex; align-items: center; gap: var(--sp-2); justify-content: flex-end; flex-wrap: wrap; padding: var(--sp-3) 0 0; }

/* ── 답안·문제 본문 ───────────────────────────────────── */

.doc { font-size: var(--t-read); line-height: 1.85; white-space: pre-wrap; max-width: 75ch; }

/* 답안 위의 표시 — 글자는 한 자도 건드리지 아니한다. 바탕만 깔고 밑줄만 긋는다 */
mark { background: transparent; color: inherit; padding: 0 1px; border-radius: 2px; }
mark.ok, .r-hl-ok   { background: var(--hit-bg);  box-shadow: inset 0 -2px 0 var(--hit); }
mark.miss, .r-hl-miss { background: var(--miss-bg); box-shadow: inset 0 -2px 0 var(--miss); }

/* ── 꼬리 ─────────────────────────────────────────────── */

footer {
  margin: var(--sp-2) 0 var(--sp-8); padding: 0;
  color: var(--muted); font-size: var(--t-sm);
}
footer p { margin: 0 0 var(--sp-1); }
.src { font-size: var(--t-sm); }

/* ═══════════════════════════════════════════════════════════════════
   앱 셸 — 내부 시범 띠 · 상단 바 · 왼쪽 메뉴            (`shell.js`)
   ═══════════════════════════════════════════════════════════════════

   ★ 셸 규칙은 전부 `.shell` 아래에 둔다.

   `.trial`  내부 시범 띠 — 맨 위, 끄는 길 없음 (규칙 13-2 ⑤)
   `.appbar` 상단 바 — 남색. 제품 이름 · 「지금 무슨 화면인가」 · 뒤로 · 밝기
   `.tabbar` 이동 메뉴 — 이름은 그대로 두고 «왼쪽 세로 메뉴»로 그린다.
             답안 쓰는 중 · 채점 중에는 없다 (`data-tabbar="none"`)
   ─────────────────────────────────────────────────────────────── */

.trial {
  /* 메뉴보다 «위»에 그려진다 — 메뉴가 화면 맨 위부터 깔리므로, 띠가 그 위에 얹혀야 가려지지 않는다 */
  position: relative; z-index: var(--z-bar);
  background: var(--trial-bg);
  border-bottom: 1px solid var(--trial-line);
  color: var(--trial-ink);
  padding: var(--sp-2) var(--sp-6);
  font-size: var(--t-sm);
  line-height: 1.5;
}
.trial strong { font-weight: var(--w-head); margin-right: var(--sp-2); }
.trial span { color: var(--trial-dim); }

.shell .appbar {
  position: sticky; top: 0; z-index: var(--z-bar);
  display: flex; align-items: center; gap: var(--sp-3);
  height: var(--bar-h); padding: 0 var(--sp-5);
  background: var(--nav); color: var(--nav-ink);
  border-bottom: 1px solid var(--nav-line);
}
/* 제품 표시 — 글자 하나를 담은 작은 네모와 이름. 그림 파일을 쓰지 않는다 */
.shell .appbar .brand {
  display: inline-flex; align-items: center; gap: var(--sp-2); flex: none;
  font-family: var(--font-display); font-weight: var(--w-head); letter-spacing: -0.01em;
  font-size: var(--t-lg); line-height: 1;
}
.shell .appbar .brand::before {
  content: "R"; display: grid; place-items: center;
  width: 24px; height: 24px; border-radius: var(--r2);
  background: var(--nav-on); color: var(--nav);
  font-size: var(--t-sm); font-weight: var(--w-head);
}
/* 메뉴가 있는 화면에서는 제품 이름의 폭이 메뉴의 폭과 같다 — 「지금 어디」가 본문과 같은 자리에서 시작한다 */
.shell.has-tabbar .appbar .brand { width: calc(var(--rail) - var(--sp-5) - var(--sp-3)); }
.shell .appbar .여기 {
  margin: 0; font-family: var(--font-body); font-size: var(--t-md); font-weight: var(--w-body);
  letter-spacing: 0; line-height: 1; color: var(--nav-dim);
  padding-left: var(--sp-3); border-left: 1px solid var(--nav-line);
}
.shell .appbar .back, .shell .appbar .theme {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  min-height: 32px; padding: 0 var(--sp-3);
  background: transparent; color: var(--nav-dim);
  border: 1px solid var(--nav-line); border-radius: var(--r2);
  font-size: var(--t-sm); line-height: 1; cursor: pointer;
  transition: background-color .12s ease-out, color .12s ease-out;
}
.shell .appbar .back::before, .shell .appbar .theme::before {
  content: ""; flex: none; width: 16px; height: 16px; background: currentColor;
  -webkit-mask: var(--icon) center / contain no-repeat; mask: var(--icon) center / contain no-repeat;
}
.shell .appbar .back { --icon: url("/icons/back.svg"); }
.shell .appbar .theme { --icon: url("/icons/theme.svg"); margin-left: auto; }
/* 남색 위에서는 닿은 표시도 밝아야 보인다 */
.shell .appbar a:focus-visible, .shell .appbar button:focus-visible { outline-color: var(--nav-ink); }
.shell .appbar .back:active, .shell .appbar .theme:active { background: var(--nav-line); }

.shell .tabbar {
  position: fixed; left: 0; bottom: 0; z-index: var(--z-menu);
  width: var(--rail);
  /* 메뉴의 «바탕»은 화면 맨 위부터 깔고, 메뉴의 «글»은 띠와 상단 바 아래에서 시작한다.
     `shell.js` 가 둘의 높이를 재어 넣는다.

     2026-09-26 에는 바탕째로 아래에서 시작하게 했다 — 바탕이 띠를 덮어서였다. 그런데 그러면
     화면을 내렸을 때 띠가 올라가 버린 자리(상단 바와 메뉴 사이)가 빈다. 메뉴가 남색이 되니
     그 빈 띠가 눈에 띄었다 (2026-09-29 에 내려 보고 찾음). 그래서 바탕은 맨 위부터 깔고,
     띠와 상단 바를 메뉴보다 위에 그린다. */
  top: 0; padding-top: var(--rail-top, 77px);
  /* 상단 바와 같은 남색 — 둘이 한 덩이가 된다. 글과 표시는 «남색 위»의 이름을 쓴다 */
  background: var(--nav); border-right: 1px solid var(--nav-line);
  display: flex; flex-direction: column;
}
.shell .tabbar::before {
  content: "자가진단";
  display: block; padding: var(--sp-5) var(--sp-5) var(--sp-3);
  font-size: var(--t-xs); font-weight: var(--w-strong); color: var(--nav-mute); letter-spacing: .04em;
}
/* 칸은 메뉴의 옆 줄에서 «안으로 들인» 덩이다. 옆구리 줄로 짚지 않는다 */
.shell .tabbar a {
  display: flex; align-items: center; gap: var(--sp-3);
  margin: 0 var(--sp-3) var(--sp-1); padding: var(--sp-2) var(--sp-3);
  min-height: var(--ctl); border-radius: var(--r-btn);
  color: var(--nav-dim); font-size: var(--t-md); line-height: 1; white-space: nowrap;
  transition: background-color .12s ease-out, color .12s ease-out;
}
/* 그림 — 파일의 색을 쓰지 않고 «모양»만 빌려 글과 같은 색으로 칠한다 */
.shell .tabbar a::before {
  content: ""; flex: none; width: 18px; height: 18px; background: currentColor;
  -webkit-mask: var(--icon) center / contain no-repeat; mask: var(--icon) center / contain no-repeat;
}
.shell .tabbar a[href="home.html"] { --icon: url("/icons/home.svg"); }
.shell .tabbar a[href="library.html"] { --icon: url("/icons/library.svg"); }
.shell .tabbar a[href="log.html"] { --icon: url("/icons/log.svg"); }
.shell .tabbar a[href="settings.html"] { --icon: url("/icons/settings.svg"); }
.shell .tabbar a.on { color: var(--nav-ink); font-weight: var(--w-strong); background: var(--nav-line); }
.shell .tabbar a.on::before { background: var(--nav-on); }
.shell .tabbar a:focus-visible { outline-color: var(--nav-ink); outline-offset: -2px; }
.shell .tabbar a:active { background: var(--nav-line); }

/* ── 본문 자리 ────────────────────────────────────────── */

/* 본문의 안 여백을 이름으로 둔다 — 화면 머리의 띠가 같은 값으로 거슬러 올라간다 */
.shell { --page-x: var(--sp-8); --page-top: var(--sp-8); }
.shell main { padding: var(--page-top) var(--page-x) var(--sp-10); min-width: 0; max-width: 1400px; }
.shell.has-tabbar main { margin-left: var(--rail); }
.shell.has-tabbar footer { margin-left: calc(var(--rail) + var(--page-x)); margin-right: var(--page-x); }
.shell footer { margin-left: var(--page-x); margin-right: var(--page-x); }

/* ── 호버는 여기 안에만 — 손을 올렸을 때 바뀌는 것은 하나씩이다 ── */

@media (hover: hover) {
  a:hover { text-decoration: underline; }
  .btn:hover { text-decoration: none; background: var(--accent-bg); }
  .btn.primary:hover { background: var(--accent-ink); border-color: var(--accent-ink); }
  .btn.danger:hover { background: var(--miss-bg); }
  .btn:disabled:hover, .btn[aria-disabled="true"]:hover { background: var(--panel); }
  .btn.primary:disabled:hover { background: var(--accent); border-color: var(--accent); }
  .tabs a:hover { text-decoration: none; color: var(--accent); }
  .shell .tabbar a:hover { text-decoration: none; background: var(--nav-line); }
  .box.dark .btn:hover { background: var(--nav-line); }
  .box.dark .btn.primary:hover { background: var(--nav-ink); border-color: var(--nav-ink); }
  tbody tr:hover td { background: var(--panel-2); }
  .shell .appbar .back:hover, .shell .appbar .theme:hover { color: var(--nav-ink); text-decoration: none; }
}

/* ── 좁을 때 — 메뉴가 위로 접힌다 ───────────────────────
   떠 있던 메뉴가 문서 안으로 들어오므로 «문서 안 차례»가 곧 자리가 된다.
   상단 바 바로 뒤에 넣는 것은 `shell.js` 의 몫이다 — 여기서는 눕히기만 한다. */

@media (max-width: 900px) {
  :root { --rail: 0px; }
  .shell .tabbar {
    position: static; width: auto; padding: 0; top: auto;
    flex-direction: row; border-right: 0; border-bottom: 1px solid var(--line2);
    overflow-x: auto;
  }
  .shell .tabbar::before { display: none; }
  .shell { --page-x: var(--sp-4); --page-top: var(--sp-5); }
  .shell .tabbar { border-bottom-color: var(--nav-line); padding: var(--sp-2) var(--sp-2); gap: var(--sp-1); }
  .shell .tabbar a { margin: 0; padding: var(--sp-2) var(--sp-3); }
  .shell.has-tabbar .appbar .brand { width: auto; }
  .shell .appbar { padding: 0 var(--sp-4); }
  .shell main { padding-bottom: var(--sp-8); }
  .page-head, .g-head { margin-bottom: var(--sp-4); padding-top: var(--sp-5); padding-bottom: var(--sp-4); }
  .page-head { grid-template-columns: minmax(0, 1fr); }
  .page-head .actionbar { grid-column: 1; grid-row: auto; justify-content: flex-start; padding-top: var(--sp-2); }
  h1 { font-size: var(--t-2xl); }
  .shell.has-tabbar > .notice { margin-left: 0; }
  .shell footer, .shell.has-tabbar footer { margin-left: var(--page-x); margin-right: var(--page-x); }
  .kv { grid-template-columns: 1fr 1fr; }
  .trial { padding: var(--sp-2) var(--sp-4); }
  .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .steps li:nth-child(2n)::after { display: none; }
}

/* ── 어두운 쪽 ──────────────────────────────────────────
   바뀌는 것은 이름의 값뿐이다. 부품마다 따로 덮어쓰지 않는다.
   높은 면일수록 «밝다» — 그림자로 띄우지 않는다. */

/*
 * 기기 설정을 따르되, 사람이 밝은 쪽을 고르면 그 뜻이 이긴다.
 * 그래서 `:root:not([data-theme="light"])` 로 감싼다.
 */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0f1722; --panel: #17212e; --panel-2: #1d2937;
    --line: #44505f; --line2: #2a3644; --control: #7a8697;
    --ink: #eef1f4; --ink2: #cdd3da; --muted: #9aa5b2;
    --nav: #0b121b; --nav-ink: #eef1f4; --nav-line: #2a3644; --nav-dim: #b9c1cb;
    --nav-mute: #8c97a5; --nav-on: #93c2f0;
    --accent: #6aa9e8; --accent-bg: #172a41; --accent-ink: #93c2f0;
    --on-accent: #0b121b; --focus: #93c2f0;
    --miss: #ee7b7b; --miss-bg: #351d1d; --hit: #63c474; --hit-bg: #173320;
    --part: #e0b652; --part-bg: #33290f;
    --trial-bg: #33290f; --trial-line: #54451c; --trial-ink: #e6cf93; --trial-dim: #c9b37d;
    --shadow: none;
  }
}

:root[data-theme="dark"] {
  --bg: #0f1722; --panel: #17212e; --panel-2: #1d2937;
  --line: #44505f; --line2: #2a3644; --control: #7a8697;
  --ink: #eef1f4; --ink2: #cdd3da; --muted: #9aa5b2;
  --nav: #0b121b; --nav-ink: #eef1f4; --nav-line: #2a3644; --nav-dim: #b9c1cb;
    --nav-mute: #8c97a5; --nav-on: #93c2f0;
  --accent: #6aa9e8; --accent-bg: #172a41; --accent-ink: #93c2f0;
  --on-accent: #0b121b; --focus: #93c2f0;
  --miss: #ee7b7b; --miss-bg: #351d1d; --hit: #63c474; --hit-bg: #173320;
  --part: #e0b652; --part-bg: #33290f;
  --trial-bg: #33290f; --trial-line: #54451c; --trial-ink: #e6cf93; --trial-dim: #c9b37d;
  --shadow: none;
}

/* ── 움직임을 줄여 달라고 한 기기 — 전부 곧바로 바뀐다 ── */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0s !important; animation-duration: 0s !important; }
}

/* ── 결과·채점 화면이 쓰는 공용 이름 (`app.js` · `grading.js` 가 짓는 마크업) ── */

.summary { display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap; margin-bottom: var(--sp-2); }
.summary .big { font-size: var(--t-4xl); line-height: 1; font-weight: var(--w-head); letter-spacing: -0.02em; color: var(--miss); font-variant-numeric: tabular-nums; }
.summary .of { font-size: var(--t-md); color: var(--muted); }
.summary .msg { flex-basis: 100%; margin: var(--sp-1) 0 0; font-size: var(--t-md); color: var(--ink2); }
.pt { padding: var(--sp-3) var(--sp-5); }
/* 더 볼 곳을 바탕색으로 칠하지 않는다 (2026-09-29). 열 가운데 아홉이 더 볼 곳이면 화면이 통째로
   붉어져 어디가 급한지 알 수 없었다. 오른끝의 붉은 표시와 «펼쳐 둔 것»이 이미 짚고 있다. */
.pt.miss { background: transparent; }
.pt-head { display: flex; justify-content: space-between; gap: var(--sp-3); align-items: center; cursor: pointer; list-style: none; }
.pt-head::-webkit-details-marker { display: none; }
.pt-head h3 { margin: 0; font-size: var(--t-md); font-weight: var(--w-head); }
/* 접힌다는 표시 — 꺾쇠. 접혀 있으면 오른쪽, 펼치면 아래를 본다.
   브라우저가 다는 세모를 걷어 놓고 대신 단 것이 없어서, 접히는지 알 길이 없었다 */
.pt-head::before {
  content: ""; flex: none; width: 7px; height: 7px; margin: 0 var(--sp-1) 0 2px;
  border-right: 1.5px solid var(--muted); border-bottom: 1.5px solid var(--muted);
  transform: rotate(-45deg); transition: transform .12s ease-out;
}
.pt[open] > .pt-head::before { transform: rotate(45deg); }
/* 이름 덩이가 남는 폭을 다 쓴다 — 판정 꼬리표는 오른끝에 붙는다 */
.pt-head > :first-child { flex: 1 1 auto; }
/* 오른끝의 판정 — 꼬리표 */
.pt-head .mark {
  flex: none; padding: var(--sp-1) var(--sp-3); border-radius: var(--r-pill);
  font-size: var(--t-xs); font-weight: var(--w-strong); line-height: 1.3;
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.pt.miss .mark { color: var(--miss); background: var(--miss-bg); }
.pt.hit  .mark { color: var(--hit); background: var(--hit-bg); }
.pt .why { margin: var(--sp-2) 0 0; font-size: var(--t-md); color: var(--ink2); max-width: 75ch; }
.pt .hint { margin: var(--sp-2) 0 0; font-size: var(--t-sm); color: var(--muted); max-width: 75ch; }
.pt .hint b { color: var(--ink2); }
.score-box { margin-top: var(--sp-2); padding-top: var(--sp-3); border-top: 1px solid var(--line); }
.score-box h2 { margin: 0 0 var(--sp-1); font-size: var(--t-md); color: var(--muted); }
.score { margin: var(--sp-1) 0 0; font-size: var(--t-xl); font-variant-numeric: tabular-nums; color: var(--muted); }
.g-head { display: block; }
.g-head .lead { margin: var(--sp-2) 0 0; }
.g-eta { margin: var(--sp-2) 0 0; }

/* 상자 머리 바로 밑에 오는 줄 목록 — 머리와 첫 줄 사이를 비우지 아니한다 */
.box > header + .r-items, .box > header + .r-sum { margin-top: calc(-1 * var(--sp-4)); }
