/* 앱 셸 스타일 — 세로 모드 스마트폰이 기준이다. 교사가 자기 폰으로 학생을 검사한다.
   색·간격·크기는 :root 토큰으로만 둔다. 화면 CSS는 토큰을 var()로 쓰고 값을 새로 만들지 않는다.
   학생이 보는 화면은 대비가 높고 요소가 크며, 색만으로 정보를 구분하지 않는다. */

:root {
  /* 색 — 본문 대비 7:1 이상(AAA). 악센트는 흰 글자와 7:1 이상. */
  --color-bg: #fffdf7;
  --color-surface: #ffffff;
  --color-text: #1a1a1a;
  --color-text-muted: #4a4a4a;
  --color-border: #1a1a1a;
  --color-accent: #0b4fb3;
  --color-on-accent: #ffffff;
  --color-focus: #ff9f00;
  /* 검사 화면: 반응 영역은 면 색과 굵은 윗선을 함께 써서 위치가 색에만 의존하지 않는다. */
  --color-response: #dbe9ff;
  --color-response-pressed: #b9d4fb;
  --color-strip: #f1ece0;
  /* 결과 화면: 억제 실패·누락·해석 불가를 알리는 색. 흰 바탕과 7:1 이상이고, 색만으로 알리지 않는다(기호·모양·글자를 함께 쓴다). */
  --color-alert: #a8320a;

  /* 간격 */
  --space-1: 0.5rem;
  --space-2: 1rem;
  --space-3: 1.5rem;
  --radius: 1rem;

  /* 크기·글자 */
  --tap-min: 3.5rem;            /* 교사 화면 버튼의 최소 높이 */
  --font-body: 1.125rem;
  --font-title: 1.75rem;
  --font-family: system-ui, -apple-system, "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", sans-serif;
  --font-emoji: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
  --stimulus-size: min(60vmin, 18rem);  /* 자극 그림 한 변. 가로·세로 어느 쪽에서도 영역 안에 들어간다 */
  --strip-height: 4rem;                  /* 자극 영역과 반응 영역 사이 수집 격자 띠 */
  --grid-rows: 1;                        /* 격자 줄 수·칸 수의 기본값. 칸 개수에 맞춰 JS가 띠 요소에 다시 적는다 */
  --grid-cols: 10;

  /* 움직임 — reduced-motion 규칙이 transition-duration을 0.01ms로 줄이므로, 그때는 이 값이 있어도 전환이 사실상 없다 */
  --motion-fast: 150ms;
}

*, *::before, *::after {
  box-sizing: border-box;
}

/* 더블탭 확대와 당겨서 새로고침을 문서 전체에서 막는다. 스크롤 자체는 막지 않는다(교사 화면). */
html, body {
  margin: 0;
  min-height: 100%;
  touch-action: manipulation;
  overscroll-behavior: none;
  -webkit-tap-highlight-color: transparent;
}

body {
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-family);
  font-size: var(--font-body);
  line-height: 1.5;
}

#app {
  min-height: 100vh;   /* dvh를 모르는 브라우저용 */
  min-height: 100dvh;
}

:focus-visible {
  outline: 0.25rem solid var(--color-focus);
  outline-offset: 0.125rem;
}

/* ---- 교사 화면 (글을 쓰는 화면) ------------------------------------------ */

.teacher-screen {
  max-width: 40rem;
  margin: 0 auto;
  /* 위·아래는 노치·홈 인디케이터 안쪽에서 시작한다(설치한 앱에서 viewport-fit=cover를 쓰거나 브라우저가 inset을 알릴 때). 보통은 0이다. */
  padding: max(var(--space-3), env(safe-area-inset-top, 0px)) var(--space-2) max(var(--space-3), env(safe-area-inset-bottom, 0px));
  /* 한글이 단어(음절) 중간에서 줄바꿈되지 않게. overflow-wrap: anywhere는 칸이 좁아지면 이것을 덮어쓰므로 쓰지 않는다.
     별칭처럼 길게 이어진 글자만 아래 .quick-start p에서 따로 꺾는다. */
  word-break: keep-all;
}

.teacher-screen h1 {
  margin: 0 0 var(--space-2);
  font-size: var(--font-title);
  line-height: 1.25;
}

.teacher-screen p {
  margin: 0 0 var(--space-2);
}

.text-muted {
  color: var(--color-text-muted);
}

/* 교사 화면 입력란(별칭, 선택 상자) — 버튼과 같은 최소 높이와 굵은 테두리로 누르기 쉽게. */
input, select {
  min-height: var(--tap-min);
  padding: var(--space-1) var(--space-2);
  border: 0.125rem solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
  color: var(--color-text);
  font: inherit;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap-min);
  padding: var(--space-1) var(--space-3);
  border: 0.125rem solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-accent);
  color: var(--color-on-accent);
  font: inherit;
  font-weight: 700;
  cursor: pointer;
  transition: background-color var(--motion-fast);
}

/* ---- 설정 화면 (교사, 한 손 조작) ------------------------------------------
   선택지는 칸 전체가 label이라 어디를 눌러도 되고, 칸 높이는 버튼과 같다. 선택 표시는 기본 라디오 점·체크 표시가
   맡으므로 색을 못 보아도 구분된다. 칸 배경은 보조일 뿐이다. */

.btn-block {
  display: flex;
  width: 100%;
}

.btn-secondary {
  background: var(--color-surface);
  color: var(--color-text);
}

.setup-section {
  min-width: 0;
  margin: 0 0 var(--space-3);
  padding: 0;
  border: 0;
}

.setup-section legend,
.field-label {
  display: block;
  margin: 0 0 var(--space-1);
  padding: 0;
  font-weight: 700;
}

.setup-screen input[type="text"],
.setup-screen select {
  display: block;
  width: 100%;
  margin-bottom: var(--space-1);
}

.choice-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: var(--space-1);
}

.choice-grid-3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.choice {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  min-height: var(--tap-min);
  padding: var(--space-1) var(--space-2);
  border: 0.125rem solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
  cursor: pointer;
}

/* 3열(검사 길이)은 칸당 글자 공간이 좁다: 폭 360px에서 칸 하나가 약 104px다. 좌우 패딩과 라디오 간격을 줄여
   두 글자 라벨이 한 줄에 들어가게 하고, 그래도 모자라면 쪼개지 않고 한 줄로 둔다. 3열에는 세 글자 이하 라벨만 둔다. */
.choice-grid-3 .choice {
  gap: calc(var(--space-1) / 2);
  padding-left: var(--space-1);
  padding-right: var(--space-1);
}

.choice-grid-3 .choice-text {
  white-space: nowrap;
}

.choice input {
  flex: none;
  width: 1.5rem;
  height: 1.5rem;
  min-height: 0;
  margin: 0;
  padding: 0;
  accent-color: var(--color-accent);
}

.choice input:checked + .choice-text {
  font-weight: 700;
}

.choice-glyph {
  font-family: var(--font-emoji);
}

/* :has를 모르는 브라우저는 이 규칙만 버리고, 선택 표시는 라디오 점이 그대로 맡는다. */
.choice:has(input:checked) {
  background: var(--color-response);
}

.notice {
  margin: 0 0 var(--space-3);
  padding: var(--space-2);
  border: 0.125rem solid var(--color-border);
  border-left-width: 0.5rem;
  border-radius: var(--radius);
  background: var(--color-surface);
}

.notice p:last-child {
  margin-bottom: 0;
}

.notice-details {
  margin-top: var(--space-1);
  font-size: 0.875rem;
  overflow-wrap: break-word;
}

.notice-details summary {
  cursor: pointer;
}

.notice-title {
  font-weight: 700;
}

.field-error {
  margin: 0 0 var(--space-1);
  font-weight: 700;
}

.quick-start {
  margin: 0 0 var(--space-3);
  padding: var(--space-2);
  border: 0.125rem solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-response);
}

/* 별칭은 길게 이어질 수 있다(공백 없는 글자). 이 요약에서만 넘치면 꺾는다. */
.quick-start p {
  overflow-wrap: break-word;
}

.quick-start .btn {
  margin-bottom: var(--space-2);
}

.setup-actions {
  display: grid;
  gap: var(--space-2);
}

/* ---- 검사 화면 (학생이 보는 화면, 문장 없음) ------------------------------
   세로: 위쪽 절반 = 자극 + 격자 띠, 아래쪽 절반 = 반응 영역 전체.
   엄지로 누르는 곳이 화면 하단 절반 어디든 반응이 되어, 조준 시간이 반응시간에 섞이지 않는다. */

.test-screen {
  display: grid;
  grid-template-areas:
    "stimulus"
    "strip"
    "response";
  /* 세 번째 행은 50%다. dvh 단위를 쓰면 dvh를 모르는 브라우저(iOS 15.4 미만 등)가 이 선언 전체를 버려
     반응 영역이 사라진다. 백분율은 아래 height가 확정해 주므로 100vh/100dvh 어느 쪽에서도 정확히 절반이다. */
  grid-template-rows: 1fr var(--strip-height) 50%;
  grid-template-columns: minmax(0, 1fr);
  height: 100vh;      /* dvh를 모르는 브라우저용 폴백 — 같은 속성에서 뒤 선언이 dvh를 알아야 덮어쓴다 */
  height: 100dvh;
  /* 세이프 에어리어: 설치(standalone)하면 노치와 홈 인디케이터가 화면을 먹을 수 있다. 하단 절반이 전부 반응 영역이므로
     위·아래 안전 영역을 비워 두고 50% 행이 "남은 높이의 절반"이 되게 한다. viewport-fit=cover가 없으면 이 값은 0이다.
     백분율 행은 이 컨테이너의 content box 높이를 기준으로 풀린다. */
  padding: env(safe-area-inset-top, 0px) 0 env(safe-area-inset-bottom, 0px);
  position: relative;   /* 중단 버튼을 구석에 둔다 */
  overflow: hidden;
  /* 핀치 확대까지 막는다: 이 화면은 스크롤하지 않으므로 팬 제스처도 필요 없다. */
  touch-action: none;
  overscroll-behavior: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

.test-stimulus {
  grid-area: stimulus;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 0;
  font-family: var(--font-emoji);
  font-size: var(--stimulus-size);
  line-height: 1;
}

/* 수집 격자 띠. 줄 수·칸 수는 칸 개수에 맞춰 JS가 --grid-rows / --grid-cols로 정한다(칸이 최대 70개라 한 줄에 못 담는다).
   칸 안의 그림은 칸 크기에 맞춰 줄어든다. 띠 밖으로 나가지 않는다(overflow: hidden) — 자극 영역을 가리지 않는다. */
.test-strip {
  grid-area: strip;
  display: grid;
  grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));
  grid-template-rows: repeat(var(--grid-rows), minmax(0, 1fr));
  align-items: stretch;
  padding: 0 var(--space-1);
  overflow: hidden;
  background: var(--color-strip);
  container-type: size;
}

.grid-cell {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  overflow: hidden;
  font-family: var(--font-emoji);
  font-size: 0.875rem;   /* 컨테이너 단위를 모르는 브라우저용 폴백 */
  font-size: min(calc(100cqh / var(--grid-rows) * 0.75), calc(100cqw / var(--grid-cols) * 0.75));
  line-height: 1;
}

/* 빈 칸은 속이 빈 동그라미, 채운 칸은 그림이다 — 색이 아니라 모양과 내용이 다르다. */
.grid-cell::before {
  content: "";
  width: 45%;
  aspect-ratio: 1;
  border: 0.125rem solid var(--color-text-muted);
  border-radius: 50%;
}

.grid-cell[data-filled="true"]::before {
  display: none;
}

/* 채워지는 연출: 칸 안에서 커지며 자리 잡는다. 300ms 이내이고 칸 밖으로 나가지 않는다. 오반응에는 없다. */
.grid-cell.is-new {
  animation: cell-fill 250ms ease-out;
}

@keyframes cell-fill {
  from { transform: scale(0.4); opacity: 0.4; }
  to { transform: scale(1); opacity: 1; }
}

.test-response {
  grid-area: response;
  background: var(--color-response);
  border-top: 0.5rem solid var(--color-border);
}

/* 누르는 동안 어두워진다. 정반응이든 아니든 똑같다 — 내용에 따라 달라지는 피드백은 주지 않는다.
   transition을 두지 않아 누르는 순간 바로 바뀐다. */
.test-response:active {
  background: var(--color-response-pressed);
}

/* 중단 버튼: 왼쪽 위 구석. 세로에서는 자극 영역, 가로에서는 왼쪽 반이라 어느 쪽에서도 반응 영역 밖이다.
   작고 흐리게 두고, 1초 넘게 눌러야 동작한다(JS). 누르는 동안 안쪽이 차오른다. */
.abort-btn {
  position: absolute;
  top: calc(var(--space-1) + env(safe-area-inset-top, 0px));   /* 노치 아래 */
  left: var(--space-1);
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  padding: 0;
  overflow: hidden;
  border: 0.125rem solid var(--color-border);
  border-radius: 50%;
  background: var(--color-surface);
  color: var(--color-text);
  font: inherit;
  opacity: 0.45;
}

/* display: flex가 hidden 속성(UA의 display: none)을 이기므로, 끝난 뒤 버튼을 숨기려면 여기서 따로 꺼야 한다. */
.abort-btn[hidden] {
  display: none;
}

.abort-btn::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--color-accent);
  opacity: 0.4;
  transform: scaleX(0);
  transform-origin: left center;
}

/* animation-duration은 JS가 버튼에 적는다(중단에 필요한 누름 시간과 한 곳에서 맞추려고). */
.abort-btn[data-holding]::after {
  animation: abort-fill linear forwards;
  animation-duration: inherit;
}

@keyframes abort-fill {
  to { transform: scaleX(1); }
}

/* 마무리 그림: 세션이 끝난 뒤에만 나온다. 격자가 덜 찼어도 항상 나온다. 자극 영역 자리에 뜬다. */
.test-completion {
  grid-area: stimulus;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-emoji);
  font-size: var(--stimulus-size);
  line-height: 1;
  pointer-events: none;
  animation: completion-bounce 1200ms ease-out;
}

@keyframes completion-bounce {
  0% { transform: scale(0.3); opacity: 0; }
  60% { transform: scale(1.15); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

/* ---- 연습 시범 (학생이 보는 화면, 글 없음) ----------------------------------
   Go 그림: 반응 영역이 스스로 눌린다(진해지고 손가락 그림이 짚는다).
   No-Go 그림: 그림이 흔들리고 반응 영역이 흐려진 채 눌리지 않는다. 시범에서만 쓰며 학생의 반응에는 쓰이지 않는다. */

.test-response {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}

.demo-hand {
  font-family: var(--font-emoji);
  font-size: var(--stimulus-size);
  line-height: 1;
  opacity: 0;
  pointer-events: none;
}

.test-response[data-demo="press"] {
  background: var(--color-response-pressed);
}

.test-response[data-demo="press"] .demo-hand {
  opacity: 1;
  animation: demo-tap 600ms ease-out;
}

.test-response[data-demo="dim"] {
  opacity: 0.35;
}

.is-demo-sway {
  animation: demo-sway 600ms ease-in-out 3;
}

@keyframes demo-tap {
  from { transform: translateY(-1.5rem) scale(1.1); }
  to { transform: translateY(0) scale(1); }
}

@keyframes demo-sway {
  0%, 100% { transform: rotate(0deg); }
  25% { transform: rotate(-9deg); }
  75% { transform: rotate(9deg); }
}

/* ---- 연습 뒤 학생 화면 (글 없음) ---------------------------------------------
   그림 하나와 (추천 확정일 때) 남은 시간 막대. 구석의 .abort-btn이 교사 제스처 버튼이다(길게 눌러야 교사용 패널이 열린다). */

.wait-screen {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  height: 100vh;      /* dvh를 모르는 브라우저용 폴백 */
  height: 100dvh;
  padding: env(safe-area-inset-top, 0px) 0 env(safe-area-inset-bottom, 0px);  /* 세이프 에어리어 — .test-screen 참고 */
  overflow: hidden;
  touch-action: none;
  overscroll-behavior: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

.wait-glyph {
  font-family: var(--font-emoji);
  font-size: var(--stimulus-size);
  line-height: 1;
}

.wait-screen .countdown {
  width: min(60vmin, 18rem);
  margin: 0;
}

/* ---- 연습 결과 (교사용 패널: 길게 눌러야 열린다) ---------------------------------- */

.countdown {
  height: 0.5rem;
  margin: 0 0 var(--space-2);
  border: 0.125rem solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
}

.countdown::after {
  content: "";
  display: block;
  height: 100%;
  background: var(--color-accent);
  transform-origin: left center;
  animation: countdown-fill linear forwards;
  animation-duration: inherit;
}

@keyframes countdown-fill {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

/* ---- 결과 화면 (교사 화면, 글을 읽는다) ---------------------------------------
   세로 모드 스마트폰이 기준이다. 타일은 2열로 접히고, 문항별 흐름 띠는 가로로 밀어서 본다(최대 100문항).
   구분은 색만으로 하지 않는다: 글자 기호(●▲○✕▽), 막대 모양(채움·속 빈·빗금·점선), 줄(고/노), 높이, 테두리 굵기·선 모양을 함께 쓴다. */

.result-top {
  margin-bottom: var(--space-2);
}

.result-screen h2 {
  margin: 0 0 var(--space-1);
  font-size: 1.25rem;
  line-height: 1.3;
}

.result-screen h3 {
  margin: 0 0 var(--space-1);
  font-size: var(--font-body);
}

.result-screen ul,
.result-screen ol {
  margin: 0 0 var(--space-2);
  padding-left: 1.25rem;
}

.result-screen li {
  margin-bottom: var(--space-1);
}

.result-section {
  margin: 0 0 var(--space-3);
  padding-top: var(--space-2);
  border-top: 0.125rem solid var(--color-border);
}

.kv-list {
  margin: 0 0 var(--space-2);
}

.kv {
  display: flex;
  gap: var(--space-1);
  padding: 0.25rem 0;
}

.kv dt {
  flex: 0 0 7.5rem;
  font-weight: 700;
}

.kv dd {
  min-width: 0;
  margin: 0;
  overflow-wrap: break-word;   /* 별칭·테마 id처럼 공백 없이 길게 이어지는 글자만 꺾는다 */
}

/* 배지: 상태마다 기호·이름·테두리 모양이 다르다(색이 아니라). 해석 불가는 면을 채워 가장 눈에 띈다. */
.badge {
  margin: 0 0 var(--space-3);
  padding: var(--space-2);
  border: 0.25rem solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
}

.badge p {
  margin: 0 0 var(--space-1);
}

.badge-title {
  font-size: 1.375rem;
  font-weight: 700;
}

.badge[data-status="reference"] {
  border-style: dashed;
}

.badge[data-status="caution"] {
  border-style: double;
  border-width: 0.5rem;
}

.badge[data-status="uninterpretable"] {
  border-color: var(--color-alert);
  background: var(--color-strip);
}

.badge-reasons {
  margin: var(--space-1) 0 0;
}

.tiles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-1);
  margin-bottom: var(--space-2);
}

.tile {
  min-width: 0;
  padding: var(--space-1) var(--space-2);
  border: 0.125rem solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
}

.tile p {
  margin: 0;
}

.tile-primary,
.tile[data-tile="anticipatory"] {
  grid-column: 1 / -1;
}

/* 억제 실패는 가장 눈에 띄게: 굵은 테두리와 큰 숫자. 참고용이면 선이 점선으로 바뀌고 글자로도 적힌다. */
.tile-primary {
  border-width: 0.375rem;
}

.tile[data-reference="true"] {
  border-style: dashed;
}

.tile-label {
  font-weight: 700;
}

.tile-hint,
.tile-note,
.tile-reference {
  font-size: 0.875rem;
}

.tile-value {
  font-size: 1.75rem;
  font-weight: 700;
  line-height: 1.3;
  overflow-wrap: break-word;
}

.tile-primary .tile-value {
  font-size: 2.75rem;
  line-height: 1.2;
}

.tile-reference {
  margin-top: 0.25rem;
  font-weight: 700;
}

.overlap-note {
  font-size: 0.9375rem;
}

/* 문항별 흐름 — 위: 전체를 한 화면 폭에 줄인 요약. 아래: 문항마다 막대 하나, 옆으로 민다. */
.flow-caption {
  margin-bottom: var(--space-1);
  font-size: 0.9375rem;
}

.overview {
  display: grid;
  grid-template-rows: 1.25rem 1.25rem;
  gap: 0.125rem;
  margin-bottom: var(--space-2);
  padding: 0.25rem;
  border: 0.125rem solid var(--color-border);
  border-radius: 0.5rem;
  background: var(--color-surface);
}

.overview-cell {
  grid-row: 1;
  align-self: end;
  min-width: 0;
  height: 40%;
  background: var(--color-accent);
}

.overview-cell[data-type="nogo"] {
  grid-row: 2;
  align-self: start;
}

.overview-cell[data-kind="early"] {
  height: 70%;
}

.overview-cell[data-kind="correctRejection"] {
  background: var(--color-text-muted);
}

.overview-cell[data-kind="commission"],
.overview-cell[data-kind="omission"] {
  height: 100%;
  background: var(--color-alert);
}

.overview-cell[data-kind="invalid"] {
  background: var(--color-strip);
}

.trial-strip {
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;   /* 옆으로 밀다가 브라우저의 뒤로 가기 제스처가 걸리지 않게 */
  -webkit-overflow-scrolling: touch;
  padding: var(--space-1);
  border: 0.125rem solid var(--color-border);
  border-radius: 0.5rem;
  background: var(--color-surface);
}

.trial-strip-inner {
  display: flex;
  gap: 0.125rem;
  width: max-content;
}

.trial-bar {
  display: flex;
  flex: none;
  flex-direction: column;
  align-items: center;
  width: 1.25rem;
}

.trial-mark {
  height: 1rem;
  font-size: 0.75rem;
  line-height: 1rem;
}

.trial-plot {
  display: flex;
  align-items: flex-end;
  width: 100%;
  height: 6rem;
  border-bottom: 0.125rem solid var(--color-border);
}

.bar-fill {
  display: block;
  box-sizing: border-box;
  width: 100%;
  min-height: 0.25rem;
}

.trial-type {
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1.25;
}

.trial-no {
  display: flex;
  justify-content: center;
  width: 100%;
  height: 1rem;
  font-size: 0.625rem;
  line-height: 1rem;
  color: var(--color-text-muted);
  white-space: nowrap;
}

/* 막대 모양: 정반응 = 채움, 조급 = 속 빈 막대, 억제 실패 = 빗금, 참기 성공 = 속 빈 동그라미, 누락 = 점선 칸, 무효 = 점. */
.trial-bar[data-kind="hit"] .bar-fill,
.legend-swatch[data-kind="hit"] {
  background: var(--color-accent);
}

.trial-bar[data-kind="early"] .bar-fill,
.legend-swatch[data-kind="early"] {
  border: 0.125rem solid var(--color-accent);
  background: var(--color-surface);
}

.trial-bar[data-kind="commission"] .bar-fill,
.legend-swatch[data-kind="commission"] {
  border: 0.125rem solid var(--color-alert);
  background: repeating-linear-gradient(45deg, var(--color-alert) 0 0.25rem, var(--color-surface) 0.25rem 0.5rem);
}

.trial-bar[data-kind="correctRejection"] .bar-fill,
.legend-swatch[data-kind="correctRejection"] {
  border: 0.125rem solid var(--color-text);
  border-radius: 50%;
  background: var(--color-surface);
}

.trial-bar[data-kind="omission"] .bar-fill,
.legend-swatch[data-kind="omission"] {
  border: 0.125rem dashed var(--color-alert);
  background: var(--color-surface);
}

.trial-bar[data-kind="invalid"] .bar-fill,
.legend-swatch[data-kind="invalid"] {
  border: 0.125rem dotted var(--color-text-muted);
  background: var(--color-strip);
}

.bar-fill[data-empty="true"] {
  height: 0.75rem;
}

.trial-bar[data-kind="commission"] .trial-mark,
.trial-bar[data-kind="omission"] .trial-mark {
  color: var(--color-alert);
  font-weight: 700;
}

.legend {
  display: grid;
  gap: 0.25rem;
  margin: var(--space-2) 0 0;
  padding: 0;
  list-style: none;
  font-size: 0.9375rem;
}

.result-screen .legend {
  padding-left: 0;
}

.legend li {
  display: flex;
  align-items: flex-start;
  gap: 0.375rem;
  margin: 0;
}

.legend-mark {
  flex: none;
  width: 1rem;
  text-align: center;
}

.legend-swatch {
  display: inline-block;
  flex: none;
  box-sizing: border-box;
  width: 1rem;
  height: 1rem;
  margin-top: 0.25rem;
}

.halves {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-1);
  margin-bottom: var(--space-1);
}

.half {
  min-width: 0;
  padding: var(--space-1) var(--space-2);
  border: 0.125rem solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
}

.half p {
  margin: 0 0 0.25rem;
}

.half strong {
  font-size: 1.25rem;
}

[data-halves][data-reference="true"] .half {
  border-style: dashed;
}

.trend {
  margin: 0;
  padding: 0;
  list-style: none;
}

.result-screen .trend {
  padding-left: 0;
}

.trend-point {
  display: grid;
  grid-template-columns: 6.5rem minmax(0, 1fr);
  gap: 0.25rem var(--space-1);
  align-items: center;
  margin: 0;
  padding: var(--space-1) 0 var(--space-1) var(--space-1);
  border-bottom: 0.125rem solid var(--color-strip);
}

.trend-point[data-current="true"] {
  border-left: 0.375rem solid var(--color-accent);
  font-weight: 700;
}

.trend-when {
  white-space: nowrap;
}

.trend-track {
  height: 1rem;
  overflow: hidden;
  border: 0.125rem solid var(--color-border);
  border-radius: 0.5rem;
  background: var(--color-surface);
}

/* 해석 불가 회차: 막대 자리를 빗금 친 빈 칸으로 둔다(모양으로 "값이 아님"을 알린다. 색만으로 알리지 않는다). */
.trend-track[data-unreliable="true"] {
  border-style: dashed;
  background: repeating-linear-gradient(135deg, var(--color-text-muted) 0 0.0625rem, transparent 0.0625rem 0.3125rem);
}

.trend-bar {
  display: block;
  height: 100%;
  background: var(--color-accent);
}

.trend-rate,
.trend-tag,
.trend-now {
  grid-column: 2;
  font-size: 0.9375rem;
}

.cautions li {
  margin-bottom: var(--space-1);
}

.interpretation li {
  font-size: 1.125rem;
}

.result-screen > .btn-block {
  margin-top: var(--space-2);
}

/* ---- 이력 화면 (교사 화면, 글을 읽고 버튼을 누른다) ----------------------------
   색만으로 구분하지 않는다: 완료/중단은 글자와 기호로, 위험한 버튼은 글자("모든 기록 지우기")와 굵은 테두리로 알린다. */

.history-screen > .btn-block {
  margin-bottom: var(--space-3);
}

.history-section {
  margin: 0 0 var(--space-3);
}

.history-section h2 {
  margin: 0 0 var(--space-1);
  font-size: 1.25rem;
}

.history-section .btn-block {
  margin-bottom: var(--space-1);
}

.history-screen input[type="text"] {
  display: block;
  width: 100%;
  margin-bottom: var(--space-1);
}

/* 4자리 숫자는 점으로 가린다(type=password는 브라우저가 비밀번호 저장을 권하므로 쓰지 않는다). */
.pin-input {
  letter-spacing: 0.5em;
  -webkit-text-security: disc;
  text-security: disc;
}

.history-screen form {
  margin: 0 0 var(--space-2);
}

.btn-danger {
  background: var(--color-alert);
  color: var(--color-on-accent);
  border-width: 0.25rem;
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.student-group {
  margin: 0 0 var(--space-1);
  border: 0.125rem solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
}

.student-group summary {
  display: flex;
  align-items: center;
  min-height: var(--tap-min);
  padding: var(--space-1) var(--space-2);
  font-weight: 700;
  cursor: pointer;
  overflow-wrap: break-word;
}

.session-list {
  margin: 0;
  padding: 0 var(--space-1) var(--space-1);
  list-style: none;
}

.session-list li + li {
  margin-top: var(--space-1);
}

.session-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0 var(--space-1);
  align-items: baseline;
  width: 100%;
  min-height: var(--tap-min);
  padding: var(--space-1) var(--space-2);
  border: 0.125rem solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-bg);
  color: var(--color-text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.session-date {
  font-weight: 700;
}

.session-state {
  grid-column: 2;
  grid-row: 1;
  font-weight: 700;
}

.session-meta {
  grid-column: 1 / -1;
  color: var(--color-text-muted);
  font-size: 0.9375rem;
}

.warning-list {
  margin: 0 0 var(--space-1);
  padding-left: var(--space-3);
  overflow-wrap: break-word;
}

/* 숨은 파일 입력: 화면에서만 감춘다(스크린리더·포커스 대상은 "백업 파일 가져오기" 버튼이다). */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
}

/* 가로로 돌려도 깨지지 않게: 반응 영역이 오른쪽 절반, 자극과 띠가 왼쪽 절반. */
@media (orientation: landscape) {
  .test-screen {
    grid-template-areas:
      "stimulus response"
      "strip    response";
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr var(--strip-height);
  }

  .test-response {
    border-top: 0;
    border-left: 0.5rem solid var(--color-border);
  }
}

/* ---- 애니메이션 끄기 -------------------------------------------------------
   두 경로: OS 설정(prefers-reduced-motion)과 교사의 수동 토글(html[data-reduced-motion="true"], Task 11).
   animation: none이 아니라 길이를 0.01ms로 줄인다 — 그래야 animationend/transitionend가 그대로 떠서
   그 이벤트로 다음 단계를 잇는 화면 코드가 멈추지 않는다. 같은 규칙을 두 곳에 쓰는 것은
   @media 안과 속성 선택자를 한 규칙으로 묶을 방법이 없기 때문이다. */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0s !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
  }
}

/* 애니메이션을 줄이면 막대 애니메이션이 0.01ms에 끝나 "이미 가득 찬" 것처럼 보인다(길게 누르는 순간 완료된 듯, 카운트다운이 끝난 듯).
   실제 타이머는 JS라 동작은 맞지만 보는 사람이 오해하므로, 그때는 채움 막대를 아예 그리지 않는다. 누르는 중에는 테두리가 굵어진다. */
@media (prefers-reduced-motion: reduce) {
  .abort-btn[data-holding]::after,
  .countdown::after {
    display: none;
  }
}

html[data-reduced-motion="true"] .abort-btn[data-holding]::after,
html[data-reduced-motion="true"] .countdown::after {
  display: none;
}

.abort-btn[data-holding] {
  border-width: 0.375rem;
}

html[data-reduced-motion="true"] *,
html[data-reduced-motion="true"] *::before,
html[data-reduced-motion="true"] *::after {
  animation-duration: 0.01ms !important;
  animation-iteration-count: 1 !important;
  animation-delay: 0s !important;
  transition-duration: 0.01ms !important;
  transition-delay: 0s !important;
  scroll-behavior: auto !important;
}
