/*
 * 타자 연습(/typing · /typing/games · /typing/test) — 이전 사이트 routes/typing/** · components/typing/** 의 화면 CSS 를 옮겼다.
 * 모든 선택자는 .typing 아래로 좁힌다(app.css 의 .chip·.notice 같은 이름과 겹치지 않게).
 * 키보드·손 그림 안은 테마와 상관없는 교육용 고정 팔레트다(손가락 색 대비를 지키기 위해).
 * 방향이 있는 속성은 논리 속성만 쓴다(ar·ur).
 */

/* ── 공통 ─────────────────────────────────────── */
.typing {
	--ty-brand: var(--wa-color-brand-fill-loud);
	--ty-ink: var(--wa-color-text-normal);
	--ty-muted: var(--wa-color-text-quiet);
	--ty-surface: var(--wa-color-surface-raised);
	--ty-lowered: var(--wa-color-surface-lowered);
	--ty-border: var(--wa-color-surface-border);
	--ty-gold: #f5b301;
	--ty-check: #8880d7;
	--finger-pinky: #ff8fa3;
	--finger-ring: #ffb27a;
	--finger-middle: #ffe08a;
	--finger-index: #8be0a4;
	--finger-thumb: #b3a0ff;
	max-inline-size: 70rem;
}
[dir='rtl'] .typing .flip { transform: scaleX(-1); }
/* Web Awesome 의 기본 버튼 모양(고정 높이·가운데 정렬·한 줄)을 걷어 낸다 — 카드처럼 쓰는 버튼이 많다 */
.typing button { block-size: auto; height: auto; margin: 0; font: inherit; }
.typing :is(.game-card, .exam-card) { align-items: stretch; justify-content: flex-start; white-space: normal; }
.typing .dash-continue { justify-content: flex-start; white-space: normal; }

/* 세 구역 탭 */
.typing .typing-tabs {
	display: inline-flex;
	gap: 0.3rem;
	margin-block-end: 1.4rem;
	padding: 0.32rem;
	border: 1px solid color-mix(in srgb, var(--ty-border) 76%, transparent);
	border-radius: 999px;
	background: color-mix(in srgb, var(--ty-lowered) 84%, transparent);
	box-shadow: inset 0 1px 1px color-mix(in srgb, var(--ty-ink) 5%, transparent), 0 8px 24px color-mix(in srgb, var(--ty-ink) 5%, transparent);
}
.typing .typing-tabs .tab {
	display: inline-flex;
	align-items: center;
	gap: 0.45rem;
	padding: 0.55rem 1.1rem;
	border-radius: 999px;
	font-size: 0.86rem;
	font-weight: 780;
	text-decoration: none;
	color: var(--ty-muted);
	transition: background var(--pes-motion), color var(--pes-motion), transform var(--pes-motion);
}
.typing .typing-tabs .tab:hover { color: var(--ty-ink); transform: translateY(-1px); }
.typing .typing-tabs .tab.active {
	background: linear-gradient(135deg, color-mix(in srgb, var(--ty-brand) 82%, #29367c), var(--ty-brand));
	color: #fff;
	box-shadow: 0 7px 18px color-mix(in srgb, var(--ty-brand) 28%, transparent);
}

/* 자판 언어 선택 */
.typing .lang-picker {
	display: flex;
	flex-wrap: wrap;
	gap: 0.3rem;
	padding: 0.25rem;
	border-radius: 999px;
	background: var(--ty-lowered);
}
.typing .lang-btn {
	padding: 0.4rem 0.8rem;
	border: none;
	border-radius: 999px;
	background: transparent;
	color: var(--ty-muted);
	font-size: 0.85rem;
	font-weight: 650;
	cursor: pointer;
	transition: background var(--pes-motion), color var(--pes-motion);
}
.typing .lang-btn:hover { color: var(--ty-ink); }
.typing .lang-btn[aria-pressed='true'] {
	background: var(--ty-brand);
	color: var(--wa-color-brand-on-loud);
	box-shadow: var(--wa-shadow-s);
}

/* 알약 버튼(연습 화면·게임) */
.typing .pill {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	padding: 0.4rem 0.85rem;
	border: 1px solid var(--ty-border);
	border-radius: 999px;
	background: var(--ty-surface);
	color: var(--ty-ink);
	font-size: 0.85rem;
	font-weight: 600;
	cursor: pointer;
}
.typing .pill:hover:not(:disabled) { filter: brightness(1.08); }
.typing .pill:disabled { opacity: 0.4; cursor: not-allowed; }
.typing .pill.icon { padding-inline: 0.6rem; }
.typing .pill[aria-pressed='false'] { opacity: 0.6; }
.typing .pill.accent {
	background: var(--ty-brand);
	border-color: transparent;
	color: #fff;
	animation: ty-retry-pulse 1s ease-in-out infinite;
}
@keyframes ty-retry-pulse { 50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--ty-brand) 30%, transparent); } }

/* 코스·시험 허브 안 작은 탭(목록 ↔ 랭킹) */
.typing .hub-tabs {
	display: inline-flex;
	gap: 0.3rem;
	margin-block-end: 1.5rem;
	padding: 0.3rem;
	border: 1px solid color-mix(in srgb, var(--ty-border) 70%, transparent);
	border-radius: 999px;
	background: color-mix(in srgb, var(--ty-lowered) 82%, transparent);
}
.typing .hub-tab {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	padding: 0.5rem 1.1rem;
	border: none;
	border-radius: 999px;
	background: transparent;
	color: var(--ty-muted);
	font-size: 0.88rem;
	font-weight: 700;
	cursor: pointer;
}
.typing .hub-tab:hover:not([aria-selected='true']) { color: var(--ty-ink); }
.typing .hub-tab[aria-selected='true'] { background: var(--ty-ink); color: var(--ty-surface); box-shadow: 0 6px 16px color-mix(in srgb, var(--ty-ink) 18%, transparent); }

/* ── 코스 첫 화면 ─────────────────────────────── */
.typing .tp-head .pes-heading-row { flex-wrap: wrap; align-items: flex-end; }

.typing .stage-wipe {
	position: fixed;
	inset: 0;
	z-index: 40;
	display: grid;
	place-items: center;
	pointer-events: none;
	background: linear-gradient(120deg, #6c8cff 0%, #7c3aed 55%, #ec4899 100%);
	animation: ty-wipe 0.72s cubic-bezier(0.7, 0, 0.3, 1) forwards;
}
/* 한쪽에서 덮었다가(0~45%) 반대쪽으로 걷는다(55~100%) */
@keyframes ty-wipe {
	0% { clip-path: inset(0 100% 0 0); }
	45%, 55% { clip-path: inset(0 0 0 0); }
	100% { clip-path: inset(0 0 0 100%); }
}
.typing .wipe-spark { font-size: 3rem; filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.35)); animation: ty-wipe-pop 0.72s ease-in-out forwards; }
@keyframes ty-wipe-pop {
	0%, 100% { transform: scale(0.4); opacity: 0; }
	45%, 55% { transform: scale(1.1); opacity: 1; }
}

.typing .score-alert {
	--accent: var(--ty-brand);
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.7rem;
	margin-block-end: 1rem;
	padding: 0.7rem 1rem;
	border: 1px solid var(--accent);
	border-radius: var(--wa-border-radius-l);
	background: color-mix(in srgb, var(--accent) 12%, var(--ty-surface));
	box-shadow: var(--wa-shadow-s);
	font-weight: 600;
	animation: ty-slide-in 0.28s ease;
}
.typing .score-alert[data-stars='3'],
.typing .score-alert[data-kind='alldone'] { --accent: var(--ty-gold); }
.typing .score-alert[data-stars='2'] { --accent: #16a34a; }
@keyframes ty-slide-in { from { opacity: 0; transform: translateY(-8px); } }
.typing .sa-stars { display: inline-flex; gap: 0.12em; font-size: 1.15rem; color: var(--accent); }
.typing .sa-text { font-size: 0.95rem; color: var(--ty-ink); }
.typing .score-alert[data-kind='alldone'] .sa-text { font-size: 1.05rem; font-weight: 800; }
.typing :is(.sa-best, .sa-retry, .sa-check) {
	padding: 0.15rem 0.55rem;
	border-radius: 999px;
	font-size: 0.82rem;
	font-weight: 800;
}
.typing .sa-best { color: #b45309; background: rgba(245, 179, 1, 0.18); }
.typing .sa-retry { color: #b45309; background: rgba(245, 158, 11, 0.18); }
.typing .sa-check { color: #5b4fc7; background: rgba(136, 128, 215, 0.18); }
.typing .sa-check.pass { color: #15803d; background: rgba(22, 163, 74, 0.16); }
.typing .sa-close {
	margin-inline-start: auto;
	padding: 0 0.2rem;
	border: none;
	background: transparent;
	color: var(--ty-muted);
	font-size: 1.2rem;
	line-height: 1;
	cursor: pointer;
}
.typing .sa-close:hover { color: var(--ty-ink); }

.typing .tp-dash {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	margin-block: 1.25rem 1rem;
	padding: 0.9rem 1.1rem;
	border: 1px solid var(--ty-border);
	border-radius: var(--wa-border-radius-l);
	background: var(--ty-lowered);
}
.typing .dash-stats { display: flex; flex-wrap: wrap; gap: 1.75rem; }
.typing .ds { display: flex; flex-direction: column; gap: 0.15rem; }
.typing .dv { font-size: 1.35rem; font-weight: 800; line-height: 1; color: var(--ty-ink); }
.typing .dv.gold { color: var(--ty-gold); }
.typing .dl { font-size: 0.72rem; color: var(--ty-muted); }
.typing .dash-continue {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.1rem;
	padding: 0.55rem 1.1rem;
	border: none;
	border-radius: var(--wa-border-radius-l);
	background: linear-gradient(135deg, var(--ty-brand), #57d998);
	color: #fff;
	cursor: pointer;
	box-shadow: 0 4px 14px color-mix(in srgb, var(--ty-brand) 35%, transparent);
	transition: transform var(--pes-motion), box-shadow var(--pes-motion);
}
.typing .dash-continue:hover { transform: translateY(-2px); }
.typing .dc-label { font-size: 0.8rem; font-weight: 800; }
.typing .dc-step { font-size: 0.72rem; opacity: 0.9; }

.typing .tp-progress { display: flex; align-items: center; gap: 0.75rem; margin-block-end: 1.5rem; }
.typing .tp-progress .track { flex: 1; block-size: 0.55rem; overflow: hidden; border-radius: 999px; background: var(--ty-lowered); }
.typing .tp-progress .fill {
	inline-size: var(--pct, 0%);
	block-size: 100%;
	border-radius: 999px;
	background: linear-gradient(90deg, var(--ty-brand), #57d998);
	transition: inline-size 0.4s ease;
}
.typing .tp-progress .ptext { font-size: 0.82rem; font-weight: 600; color: var(--ty-muted); white-space: nowrap; }

.typing .lesson-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: 1rem; }
.typing .lesson-card {
	position: relative;
	display: block;
	overflow: hidden;
	padding: 1.15rem 1.2rem 1.1rem;
	text-align: start;
	cursor: pointer;
	transition: border-color var(--pes-motion), transform var(--pes-motion), box-shadow var(--pes-motion);
}
/* 시작 쪽 띠 — 단계마다 손가락 색 */
.typing .lesson-card::before {
	content: '';
	position: absolute;
	inset-block: 0;
	inset-inline-start: 0;
	inline-size: 4px;
	background: var(--accent);
	opacity: 0.85;
}
.typing .lesson-card:hover { border-color: var(--accent); transform: translateY(-3px); box-shadow: var(--wa-shadow-l); }
.typing .lesson-card:focus-visible { outline: 2px solid var(--ty-brand); outline-offset: 2px; }
.typing .lesson-card.done { border-color: var(--wa-color-success-fill-loud); }
.typing .lesson-card.mastered { border-color: var(--ty-gold); box-shadow: 0 0 0 1px var(--ty-gold), var(--wa-shadow-s); }
.typing .lc-head { display: flex; align-items: center; justify-content: space-between; margin-block-end: 0.65rem; }
.typing .lc-num {
	display: inline-grid;
	place-items: center;
	inline-size: 2.1rem;
	block-size: 2.1rem;
	border-radius: 0.6rem;
	background: var(--accent);
	color: #12141c;
	font-size: 1.05rem;
	font-weight: 800;
	box-shadow: inset 0 -2px 6px rgba(0, 0, 0, 0.12);
}
.typing .lc-stars { display: inline-flex; gap: 0.05rem; font-size: 0.9rem; color: var(--ty-muted); }
.typing .lc-stars.gold { color: var(--ty-gold); }
.typing .lc-arrow { color: var(--ty-muted); transition: color var(--pes-motion), translate var(--pes-motion); }
.typing .lesson-card:hover .lc-arrow { color: var(--accent); translate: 3px; }
[dir='rtl'] .typing .lesson-card:hover .lc-arrow { translate: -3px; }
.typing .lc-title { display: block; margin-block-end: 0.3rem; font-size: 1.1rem; font-weight: 700; line-height: 1.25; color: var(--ty-ink); }
.typing .lc-tag {
	display: -webkit-box;
	overflow: hidden;
	min-block-size: 2.4em;
	font-size: 0.82rem;
	line-height: 1.45;
	color: var(--ty-muted);
	-webkit-line-clamp: 2;
	line-clamp: 2;
	-webkit-box-orient: vertical;
}
.typing .lc-state {
	display: inline-block;
	margin-block-start: 0.5rem;
	padding: 0.12rem 0.5rem;
	border-radius: 999px;
	background: var(--ty-lowered);
	color: var(--ty-muted);
	font-size: 0.7rem;
	font-weight: 700;
}
.typing .lc-state[data-state='practicing'] { color: #b45309; background: rgba(245, 158, 11, 0.16); }
.typing .lc-state[data-state='passed'] { color: #15803d; background: rgba(22, 163, 74, 0.14); }
.typing .lc-state[data-state='mastered'] { color: #a16207; background: rgba(245, 179, 1, 0.2); }
.typing .lc-foot {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.35rem;
	margin-block-start: 0.85rem;
	padding-block-start: 0.7rem;
	border-block-start: 1px solid var(--ty-border);
	color: var(--ty-muted);
	font-size: 0.76rem;
	font-weight: 600;
}
.typing .lc-foot .fi { color: var(--accent); }
.typing .lesson-card.done .lc-foot .fi { color: var(--wa-color-success-fill-loud); }
.typing .lc-check {
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
	margin-inline-start: auto;
	padding: 0.2rem 0.55rem;
	border: 1px solid var(--ty-check);
	border-radius: 999px;
	background: transparent;
	color: #5b4fc7;
	font-size: 0.72rem;
	font-weight: 700;
	cursor: pointer;
}
.typing .lc-check:hover { background: rgba(136, 128, 215, 0.14); }

.typing .legend {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem 1rem;
	margin-block-start: 1.75rem;
	padding: 0.85rem 1.1rem;
	border-radius: var(--wa-border-radius-l);
	background: var(--ty-lowered);
	font-size: 0.85rem;
}
.typing .legend-item { display: inline-flex; align-items: center; gap: 0.35rem; color: var(--ty-muted); }
.typing .swatch { display: inline-block; inline-size: 0.85rem; block-size: 0.85rem; border-radius: 0.25rem; background: var(--finger-pinky); }
.typing .swatch[data-finger='ring'] { background: var(--finger-ring); }
.typing .swatch[data-finger='middle'] { background: var(--finger-middle); }
.typing .swatch[data-finger='index'] { background: var(--finger-index); }
.typing .swatch[data-finger='thumb'] { background: var(--finger-thumb); }

/* ── 레벨 테스트 화면(코스 첫 화면) — 나의 키보드 레벨 1단~9단 ─────── */
/* 들어오자마자 시작 단추가 노트북 한 화면(높이 600px 안팎) 안에 보이도록 코스 첫 화면의 위쪽을 줄인다 */
.typing-course .typing-tabs { margin-block-end: 0.9rem; }
.typing-course .tp-head { gap: 0.4rem; padding-block-end: 0.9rem; }
.typing-course .tp-head .hub-tabs { justify-self: start; margin: 0.35rem 0 0; }
.typing .level-card {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.6rem;
	padding: clamp(1rem, 2.5vw, 1.4rem) clamp(1rem, 3vw, 2rem);
	border: 1px solid var(--ty-border);
	border-radius: var(--wa-border-radius-l);
	background:
		radial-gradient(ellipse 70% 60% at 50% 0%, color-mix(in srgb, var(--ty-brand) 12%, transparent), transparent 70%),
		var(--ty-surface);
	box-shadow: var(--wa-shadow-s);
	text-align: center;
}
.typing .level-card[data-state='master'] {
	border-color: var(--ty-gold);
	background: radial-gradient(ellipse 70% 60% at 50% 0%, color-mix(in srgb, var(--ty-gold) 22%, transparent), transparent 70%), var(--ty-surface);
}
/* 윗줄 — 지금 레벨(왼쪽)과 1단~9단 계단(오른쪽). 좁으면 위아래로 */
.typing .lv-top { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: center; gap: 0.75rem 2rem; inline-size: 100%; }
.typing .lv-now { display: flex; flex-direction: column; align-items: center; gap: 0.3rem; min-inline-size: 8rem; }
.typing .lv-heading { margin: 0; color: var(--ty-muted); font-size: 0.85rem; font-weight: 700; letter-spacing: 0.02em; }
.typing .lv-dan {
	font-size: clamp(2.4rem, 6vw, 3.4rem);
	font-weight: 900;
	line-height: 1;
	letter-spacing: -0.03em;
	background: linear-gradient(135deg, var(--ty-brand), #22c38e);
	background-clip: text;
	color: transparent;
}
.typing .lv-dan.none { font-size: 1.5rem; letter-spacing: 0; }
.typing .level-card[data-state='master'] .lv-dan { background-image: linear-gradient(135deg, #f59e0b, #facc15); }
.typing .lv-master {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	padding: 0.2rem 0.8rem;
	border-radius: 999px;
	background: color-mix(in srgb, var(--ty-gold) 22%, transparent);
	color: #a16207;
	font-weight: 800;
}
.wa-dark .typing .lv-master { color: #fcd34d; }

/* 1단 → 9단 계단 — 통과한 단은 채우고, 다음 단은 테두리가 숨 쉬고, 남은 단은 흐리게 */
.typing .lv-ladder {
	display: flex;
	align-items: flex-end;
	justify-content: center;
	flex: 1 1 18rem;
	gap: 0.3rem;
	inline-size: 100%;
	min-inline-size: 0;
	max-inline-size: 30rem;
	margin: 0;
	padding: 0;
	list-style: none;
}
.typing .lv-ladder li {
	display: flex;
	flex: 1 1 0;
	min-inline-size: 0;
	align-items: flex-end;
	justify-content: center;
	box-sizing: border-box;
	block-size: calc(1.5rem + var(--n) * 0.34rem);
	padding-block-end: 0.3rem;
	border: 1px solid var(--ty-border);
	border-radius: 0.5rem 0.5rem 0.3rem 0.3rem;
	background: var(--ty-lowered);
	color: var(--ty-muted);
	font-size: 0.7rem;
	font-weight: 700;
	white-space: normal;
	text-align: center;
}
.typing .lv-ladder li[data-state='passed'] { border-color: transparent; background: linear-gradient(180deg, #57d998, var(--ty-brand)); color: #fff; }
.typing .lv-ladder li[data-state='passed']:last-child { background: linear-gradient(180deg, #facc15, #f59e0b); }
.typing .lv-ladder li[data-state='next'] {
	border: 2px solid var(--ty-brand);
	background: color-mix(in srgb, var(--ty-brand) 10%, var(--ty-surface));
	color: var(--ty-brand);
	animation: ty-level-next 1.6s ease-in-out infinite;
}
@keyframes ty-level-next { 50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--ty-brand) 22%, transparent); } }

.typing .lv-text { max-inline-size: 36rem; margin: 0; color: var(--ty-ink); line-height: 1.55; }
.typing .lv-goal {
	margin: 0;
	padding: 0.35rem 0.9rem;
	border-radius: 999px;
	background: var(--ty-lowered);
	color: var(--ty-ink);
	font-size: 0.9rem;
	font-weight: 700;
}
.typing .lv-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 0.6rem; margin-block-start: 0.25rem; }
.typing .lv-primary {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.75rem 1.6rem;
	border: none;
	border-radius: 999px;
	background: linear-gradient(135deg, var(--ty-brand), #22c38e);
	color: #fff;
	font-size: 1.05rem;
	font-weight: 800;
	cursor: pointer;
	box-shadow: 0 6px 18px color-mix(in srgb, var(--ty-brand) 35%, transparent);
	transition: transform var(--pes-motion), box-shadow var(--pes-motion);
}
.typing .lv-primary:hover:not(:disabled) { transform: translateY(-2px); }
.typing .lv-primary:disabled { opacity: 0.6; cursor: wait; }
.typing .lv-primary:focus-visible { outline: 2px solid var(--ty-brand); outline-offset: 3px; }
.typing .lv-hint { color: var(--ty-muted); font-size: 0.78rem; }
.typing .lv-town { display: flex; align-items: center; gap: 0.4rem; margin: 0; color: var(--ty-muted); font-size: 0.8rem; }
.typing .lv-town i { color: #16a34a; }
@media (prefers-reduced-motion: reduce) {
	.typing .lv-ladder li[data-state='next'] { animation: none; }
}

/* ── 연습 화면 ────────────────────────────────── */
/*
 * 연습할 글자·손·키보드가 노트북 한 화면(높이 600px 안팎)에 함께 들어오게 한다.
 * 위쪽은 두 줄(버튼·점수·기록 / 단계·라운드·새 키)로 줄이고, 글자 칸·손·키보드는 남은 높이(--pr-room)를 나눠 쓴다.
 * --pr-room = 화면 높이 − (사이트 머리 + 위쪽 두 줄 + 사이 간격). 좁은 화면은 폭이 먼저 줄인다.
 */
.typing .practice {
	--pr-gap: 0.6rem;
	--pr-room: max(18rem, 100dvh - 14.5rem);
	container: practice / inline-size;
	display: flex;
	flex-direction: column;
	gap: var(--pr-gap);
	min-inline-size: 0;
}
.typing .practice.reduced *,
.typing .practice.reduced *::before,
.typing .practice.reduced *::after { animation: none !important; transition: none !important; }

/* 연습 중에는 본문 위의 리엔 안내·진도 한 줄과 위쪽 여백을 걷는다(읽던 안내는 멈춘다 — public/js/pages/typing-course.js) */
.content:has(> .typing-course.is-practicing) > :is(.page-guide, .study-inline) { display: none; }
.typing.is-practicing { padding-block-start: 0; }

/*
 * 첫 줄(단계 이동 · 연습 점수 · 기록)과 둘째 줄(단계 · 라운드 · 새 키 · 도구)은 줄을 바꾸지 않는다 —
 * 점수가 커지거나 안내 보기 단추가 나타나도 아래 글자·손·키보드가 들썩이지 않게, 모자라면 단계 이름이 말줄임으로 줄어든다.
 * 휴대폰 폭(40rem 미만)만 줄을 바꾼다.
 */
.typing :is(.pr-bar, .pr-status) { display: flex; flex-wrap: wrap; align-items: center; }
@container practice (min-width: 40rem) {
	.typing :is(.pr-bar, .pr-status) { flex-wrap: nowrap; }
}
/* 휴대폰 폭은 위쪽이 네 줄쯤으로 접히니 그만큼 남은 높이를 덜어 준다 */
@container practice (max-width: 39.99rem) {
	.typing .practice > * { --pr-room: max(18rem, 100dvh - 22rem); }
}
.typing .pr-bar { gap: 0.5rem; }
.typing :is(.pr-nav, .pr-tools) { display: flex; flex-shrink: 0; align-items: center; gap: 0.3rem; }
.typing .pr-tools { margin-inline-start: auto; }
/* 좁으면 단추는 동그란 아이콘만 — 글자는 화면 읽기 프로그램에만 남긴다(이름은 title 로도 보인다) */
.typing :is(.pr-nav, .pr-tools) .pill { justify-content: center; min-inline-size: 2.4rem; block-size: 2.4rem; box-sizing: border-box; padding: 0 0.6rem; white-space: nowrap; }
.typing :is(.pr-nav, .pr-tools) .pill > span {
	position: absolute;
	inline-size: 1px;
	block-size: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}
@container practice (min-width: 62rem) {
	.typing :is(.pr-nav, .pr-tools) .pill > span { position: static; inline-size: auto; block-size: auto; overflow: visible; clip-path: none; }
	.typing :is(.pr-nav, .pr-tools) .pill:not(.icon) { padding-inline: 0.85rem; }
}
.typing .pr-tools .help-toggle { padding-inline: 0.85rem; }
.typing .pill.skip { border-color: var(--ty-check); color: #8873db; }
.typing .pill.skip:disabled { border-color: var(--ty-border); color: inherit; }
.typing .pr-chips { display: flex; flex-shrink: 0; gap: 0.3rem; }
.typing .pr-chips .chip {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	min-inline-size: 3.2rem;
	block-size: 2.4rem;
	box-sizing: border-box;
	padding: 0 0.45rem;
	border: 1px solid var(--ty-border);
	border-radius: var(--wa-border-radius-m);
	background: var(--ty-surface);
	line-height: 1.15;
}
.typing .pr-chips .cv { font-size: 0.95rem; font-weight: 700; color: var(--ty-brand); }
.typing .pr-chips .cl { font-size: 0.6rem; color: var(--ty-muted); white-space: nowrap; }
.typing .pr-chips .acc[data-state='ok'] { border-color: var(--wa-color-success-fill-loud); }
.typing .pr-chips .acc[data-state='ok'] .cv { color: var(--wa-color-success-fill-loud); }
.typing .pr-chips .acc[data-state='low'] { border-color: var(--wa-color-warning-fill-loud); }
.typing .pr-chips .acc[data-state='low'] .cv { color: var(--wa-color-warning-fill-loud); }

/* 연습 점수 · 콤보 — 버튼과 같은 높이의 한 줄. 불꽃과 축하 문구는 줄 밖으로 넘쳐 아래 글자 칸 위에 잠깐 뜬다 */
.typing .score-stage {
	position: relative;
	z-index: 3;
	isolation: isolate;
	display: flex;
	flex: 1 1 auto;
	align-items: center;
	gap: 0.75rem;
	min-inline-size: 0;
	block-size: 2.4rem;
	box-sizing: border-box;
	padding-inline: 0.8rem;
	border: 1px solid #7278d7;
	border-radius: 999px;
	background: radial-gradient(ellipse at 0 0, #413477, transparent 65%), linear-gradient(115deg, #171d3c, #172b42);
	color: #fff;
	box-shadow: 0 4px 14px #25225325;
}
.typing .score-stage.fever { border-color: #ffca6a; background: radial-gradient(ellipse at 0 0, #70345f, transparent 65%), linear-gradient(115deg, #282041, #38305b); }
.typing .score-number,
.typing .combo-panel { position: relative; z-index: 1; display: flex; align-items: center; gap: 0.35rem; min-inline-size: 0; }
.typing .score-number i { color: #fdd573; font-size: 0.85rem; }
.typing .score-number strong {
	display: inline-block;
	font-size: 1.35rem;
	font-variant-numeric: tabular-nums;
	line-height: 1;
	letter-spacing: -0.03em;
	text-shadow: 0 0 16px #aea0ff65;
}
.typing .score-number strong.pop { animation: ty-score-pop 0.18s ease-out; }
/* 얻은 점수는 숫자 위에 떠올랐다 사라진다 — 줄 폭을 바꾸지 않는다 */
.typing .score-gain { position: absolute; inset-block-end: 70%; inset-inline-start: 100%; color: #74f5d1; font-size: 0.8rem; font-weight: 800; white-space: nowrap; }
.typing .score-gain.float { animation: ty-points-rise 0.65s ease-out both; }
.typing .combo-panel { flex: 1; align-self: stretch; }
.typing .combo-panel i { color: #ffbd67; }
.typing .combo-panel strong { overflow: hidden; font-size: 0.85rem; white-space: nowrap; text-overflow: ellipsis; }
.typing .multiplier {
	padding: 0.05rem 0.45rem;
	border: 1px solid #ffffff35;
	border-radius: 0.5rem;
	background: #ffffff18;
	color: #ffe08b;
	font-size: 0.9rem;
	font-weight: 900;
}
.typing .combo-track { flex: 1; min-inline-size: 0; block-size: 0.4rem; overflow: hidden; border-radius: 1rem; background: #ffffff1c; }
.typing .combo-track span {
	display: block;
	inline-size: var(--pct, 0%);
	block-size: 100%;
	border-radius: inherit;
	background: linear-gradient(90deg, #a697ff, #67efd5, #ffdf84);
	box-shadow: 0 0 10px #80efda;
	transition: inline-size 0.18s ease-out;
}
/*
 * 축하 문구 — 콤보 칸 위에 겹쳐 잠깐 뜬다(자리를 차지하지 않아 아래 줄을 가리지도, 밀지도 않는다).
 * 비어 있을 때도 화면 읽기 프로그램이 알림을 놓치지 않게 숨기지 않고 투명하게만 둔다.
 */
.typing .celebration {
	position: absolute;
	inset: 0.2rem -0.3rem;
	z-index: 2;
	overflow: hidden;
	align-content: center;
	padding-inline: 0.6rem;
	border-radius: 999px;
	color: #ffe3a0;
	font-size: 0.8rem;
	font-weight: 700;
	text-align: center;
	white-space: nowrap;
	text-overflow: ellipsis;
	pointer-events: none;
}
.typing .celebration:not(:empty) { background: #2d2f63; box-shadow: 0 0 0 1px #ffffff26; animation: ty-celebrate-in 0.2s ease-out; }
@keyframes ty-celebrate-in { from { opacity: 0; transform: scale(0.94); } }
.typing .fireworks { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
.typing .spark {
	position: absolute;
	inset-block-start: 55%;
	inset-inline-start: var(--origin);
	inline-size: 5px;
	block-size: 5px;
	border-radius: 50%;
	background: hsl(var(--hue) 100% 74%);
	box-shadow: 0 0 9px 2px hsl(var(--hue) 100% 65% / 0.75);
	opacity: 0;
	animation: ty-burst 1.15s var(--delay) cubic-bezier(0.16, 0.7, 0.4, 1) both;
}
.typing .spark.ribbon { inline-size: 4px; block-size: 10px; border-radius: 1px; }
.typing .shockwave {
	position: absolute;
	inset-block-start: 55%;
	inset-inline-start: var(--origin);
	inline-size: 30px;
	block-size: 30px;
	margin: -15px;
	border: 2px solid #c8c1ff;
	border-radius: 50%;
	animation: ty-shockwave 0.75s ease-out both;
}
@keyframes ty-burst {
	0% { transform: translate(0, 0) scale(0.3); opacity: 0; }
	12%, 65% { opacity: 1; }
	100% { transform: translate(var(--dx), var(--dy)) rotate(150deg) scale(0.25); opacity: 0; }
}
@keyframes ty-shockwave { from { transform: scale(0.1); opacity: 0.65; } to { transform: scale(7); opacity: 0; } }
@keyframes ty-score-pop { from { transform: scale(1.08); color: #a2ffe5; } }
@keyframes ty-points-rise {
	from { opacity: 1; transform: translateY(9px) scale(1.2); }
	to { opacity: 0; transform: translateY(-20px) scale(0.85); }
}

/* 둘째 줄 — 단계 이름 · 라운드 진행 · 새 키(또는 확인 시험 배지) · 안내 보기 */
.typing .pr-status { gap: 0.3rem 0.6rem; min-block-size: 2.4rem; color: var(--ty-muted); font-size: 0.82rem; }
.typing .pr-step {
	flex-shrink: 0;
	padding: 0.15rem 0.5rem;
	border-radius: 999px;
	background: var(--ty-lowered);
	color: var(--ty-brand);
	font-size: 0.8rem;
	font-weight: 700;
	white-space: nowrap;
}
.typing .pr-title { flex: 0 1 auto; min-inline-size: 0; overflow: hidden; color: var(--ty-ink); font-size: var(--wa-font-size-m); white-space: nowrap; text-overflow: ellipsis; }
.typing .round-dots { display: flex; flex-shrink: 0; gap: 0.3rem; margin-inline-start: 0.4rem; }
.typing .rdot {
	inline-size: 0.7rem;
	block-size: 0.7rem;
	border-radius: 50%;
	background: var(--ty-border);
	transition: background 0.2s ease, transform 0.2s ease;
}
.typing .rdot.done { background: var(--wa-color-success-fill-loud); }
.typing .rdot.cur { background: var(--ty-brand); transform: scale(1.25); }
/* 확인 시험 라운드는 테두리 고리로, 건너뛴 라운드는 빈 점으로 */
.typing .rdot.check { box-shadow: 0 0 0 2px var(--ty-check); }
.typing .rdot.skipped { box-sizing: border-box; border: 2px dashed var(--ty-muted); background: transparent; }
.typing .round-label { flex: 0 3 auto; min-inline-size: 0; overflow: hidden; font-weight: 700; color: var(--ty-ink); white-space: nowrap; text-overflow: ellipsis; }

/* 새 키 · 확인 시험 배지 · 레벨 테스트 배지 · 안내 보기 */
.typing .level-badge {
	display: inline-flex;
	flex-shrink: 0;
	align-items: center;
	gap: 0.4rem;
	padding: 0.2rem 0.75rem;
	border-radius: 999px;
	background: linear-gradient(135deg, var(--ty-brand), #22c38e);
	color: #fff;
	font-size: 0.85rem;
	font-weight: 800;
	white-space: nowrap;
}
.typing .check-badge {
	display: inline-flex;
	flex-shrink: 0;
	align-items: center;
	gap: 0.4rem;
	padding: 0.2rem 0.7rem;
	border-radius: 999px;
	background: #8771ee;
	color: #fff;
	font-size: 0.85rem;
	font-weight: 800;
	white-space: nowrap;
}
.typing .new-keys { display: flex; flex-shrink: 0; align-items: center; gap: 0.3rem; }
.typing .keycap {
	display: inline-grid;
	place-items: center;
	min-inline-size: 1.9rem;
	block-size: 1.9rem;
	padding-inline: 0.4rem;
	border-radius: 0.45rem;
	background: var(--kc, #c4c8d4);
	color: #141414;
	font-family: var(--wa-font-family-code);
	font-size: 1rem;
	font-weight: 800;
	box-shadow: inset 0 -3px 0 rgba(0, 0, 0, 0.18);
}
.typing .keycap.wide { font-size: 0.8rem; }

/* 연습 글자 — 멀리서도 읽히게 크게. 칸 높이는 남은 높이의 1/4 쯤 — 넘치면 칸 안에서 지금 글자를 따라간다(typing-course.js markText) */
.typing .pr-text {
	position: relative;
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	justify-content: center;
	gap: 0.2rem 0.5rem;
	min-block-size: 4rem;
	max-block-size: clamp(5.5rem, calc(var(--pr-room) * 0.26), 16rem);
	overflow-y: auto;
	scrollbar-gutter: stable;
	box-sizing: border-box;
	padding: 0.6rem 1rem;
	border: 1px solid var(--ty-border);
	border-radius: var(--wa-border-radius-l);
	background: var(--ty-surface);
	font-family: var(--wa-font-family-code);
}
.typing .pr-text .unit { display: inline-flex; flex-direction: column; align-items: center; padding: 0.1rem 0.15rem; border-radius: 0.3rem; line-height: 1.1; }
.typing .pr-text .glyph { font-size: clamp(2rem, calc(var(--pr-room) * 0.075), 3rem); }
.typing .pr-text .hint { font-size: 1rem; opacity: 0.7; }
.typing .pr-text.no-hint .hint { display: none; }
.typing .pr-text .unit.done .glyph { color: var(--wa-color-success-fill-loud); }
.typing .pr-text .unit.pending { color: var(--ty-muted); }
.typing .pr-text .unit.current { background: var(--ty-brand); color: #fff; }
.typing .pr-text .unit.current .hint { color: #fff; opacity: 0.85; }
.typing .pr-text.mistake .unit.current { background: #b4233d; outline: 2px solid #b4233d40; }

/* 라운드·단계를 마친 뒤의 안내 — 글자 칸 아래쪽에 겹쳐 뜬다. 떴다 사라질 때 손·키보드가 들썩이지 않게 자리를 차지하지 않는다 */
.typing .pr-hint {
	position: relative;
	z-index: 2;
	display: flex;
	align-items: center;
	align-self: center;
	gap: 0.5rem;
	block-size: 2rem;
	box-sizing: border-box;
	max-inline-size: calc(100% - 2rem);
	margin-block-start: calc(-2.4rem - var(--pr-gap));
	margin-block-end: 0.4rem;
	padding-inline: 0.9rem;
	border: 1px solid currentColor;
	border-radius: 999px;
	background: var(--ty-surface);
	box-shadow: var(--wa-shadow-s);
	font-size: 0.9rem;
	font-weight: 600;
}
.typing .pr-hint .dot { flex: 0 0 auto; inline-size: 0.85rem; block-size: 0.85rem; border-radius: 50%; background: var(--wa-color-success-fill-loud); }
.typing .pr-hint.done { color: var(--wa-color-success-fill-loud); }
.typing .pr-hint.fail { color: var(--wa-color-warning-fill-loud); font-weight: 700; }
.typing .pr-hint.fail .dot { background: var(--wa-color-warning-fill-loud); }

/* 손 그림(가로:세로 = 420:226)은 남은 높이의 30%, 키보드(932:332)는 44% — 폭이 먼저 차면 폭에 맞춘다 */
.typing .hand-guide { inline-size: min(100%, 600px, calc(var(--pr-room) * 0.3 * 1.858)); align-self: center; }

/* 손 그림 */
.typing svg.hands { display: block; inline-size: 100%; block-size: auto; }
.typing svg.hands :is(.finger, .palm) { transition: fill 0.15s ease, opacity 0.18s ease; }
.typing svg.hands.is-typing :is(.rest, .palm) { opacity: 0.6; }
.typing svg.hands .glow { filter: drop-shadow(0 0 5px var(--glow)); animation: ty-hand-breathe 1.1s ease-in-out infinite; }
.typing svg.hands .cap { filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.35)); }
.typing svg.hands .reach { animation: ty-reach-bob 0.7s ease-in-out infinite; }
@keyframes ty-hand-breathe {
	0%, 100% { filter: drop-shadow(0 0 4px var(--glow)); }
	50% { filter: drop-shadow(0 0 9px var(--glow)); }
}
@keyframes ty-reach-bob { 0%, 100% { opacity: 0.6; } 50% { opacity: 1; } }

/* 화면 키보드 — 키보드는 언제나 왼쪽→오른쪽(실제 자판 배열) */
.typing .keyboard-guide { direction: ltr; }
.typing svg.kbd {
	display: block;
	inline-size: min(100%, calc(var(--pr-room) * 0.44 * 2.807));
	block-size: auto;
	margin-inline: auto;
	box-sizing: border-box;
	padding: 0.25rem;
	border: 1px solid #262a3a;
	border-radius: var(--wa-border-radius-l);
	background: radial-gradient(120% 90% at 50% -10%, rgba(136, 128, 215, 0.18), transparent 60%), linear-gradient(180deg, #171a26 0%, #0f1118 100%);
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04), 0 10px 30px -18px rgba(0, 0, 0, 0.7);
}
.typing svg.kbd rect { transition: fill 0.12s ease; }
.typing svg.kbd .key { transition: opacity 0.18s ease; }
.typing svg.kbd .sheen { stroke: rgba(255, 255, 255, 0.1); stroke-width: 1.5; }
.typing svg.kbd .key.lit .sheen { stroke: rgba(255, 255, 255, 0.45); }
/* 타자 중 목표가 아닌 키 — 채움·글자·돌기를 함께 물린다 */
.typing svg.kbd .rest { opacity: 0.4; }
.typing svg.kbd :is(.ring, .halo) { transform-box: fill-box; transform-origin: center; }
.typing svg.kbd .halo { opacity: 0.28; filter: blur(6px); animation: ty-kbd-halo 1.1s ease-in-out infinite; }
.typing svg.kbd .ring { filter: drop-shadow(0 0 6px var(--glow)); animation: ty-kbd-ring 1.1s ease-in-out infinite; }
.typing svg.kbd .arrow { stroke-dasharray: 6 6; animation: ty-kbd-flow 0.6s linear infinite; }
@keyframes ty-kbd-ring {
	0%, 100% { transform: scale(1); stroke-opacity: 1; }
	50% { transform: scale(1.07); stroke-opacity: 0.7; }
}
@keyframes ty-kbd-halo {
	0%, 100% { opacity: 0.22; transform: scale(1); }
	50% { opacity: 0.4; transform: scale(1.12); }
}
@keyframes ty-kbd-flow { to { stroke-dashoffset: -12; } }
/* 움직임 줄이기 · 효과 끄기: 링·광채·화살표는 보이고 움직임만 멈춘다 */
.typing svg.still :is(.ring, .halo, .arrow, .glow, .reach) { animation: none; }
.typing svg.still :is(rect, .key, .finger, .palm) { transition: none; }

/* ── 연습 정원(배경) ──────────────────────────── */
/*
 * 단계가 높고 연습 점수가 높을수록 잔디 몇 포기 → 꽃밭 → 해·구름·코스모스·벌·나비의 정원으로 자란다(public/js/typing/garden-view.js).
 * 글자·손·키보드 뒤에 깔리는 배경이라 아무것도 가리지 않는다. 풍경은 키보드처럼 언제나 왼쪽→오른쪽이다.
 * 크기와 자리는 정원 칸에 대한 비율(cqi · cqb)이라 화면 크기가 바뀌어도 같은 그림이다.
 * 움직임 줄이기·이펙트 끄기 때는 .practice.reduced 가 흔들림·날갯짓·자라는 움직임을 모두 멈춘다.
 */
/* 키보드·손이 숨는 확인 시험·레벨 테스트에서도 연습 칸이 화면 아래까지 차서 정원이 납작해지지 않는다 */
.typing .practice { position: relative; isolation: isolate; min-block-size: max(24rem, 100dvh - 7.5rem); }
.typing .garden { position: absolute; inset: -0.75rem -1rem -0.5rem; z-index: -1; pointer-events: none; direction: ltr; }
.typing .garden-scene {
	position: absolute;
	inset: 0;
	overflow: hidden;
	container-type: size;
	border-radius: var(--wa-border-radius-l);
	/* 위쪽 두 줄 뒤는 비워 두고(글자가 또렷하게) 아래로 갈수록 풍경이 짙어진다 */
	mask-image: linear-gradient(to bottom, transparent 0, #000 26%, #000 94%, transparent);
}
.typing .garden-scene > * { position: absolute; }
.typing .garden-scene svg { display: block; inline-size: 100%; block-size: 100%; overflow: visible; }

/* 하늘 · 언덕 · 햇살 — 풀밭이 되는 단계부터 천천히 밝아진다 */
.typing .g-sky { inset: 0; z-index: -2; background: linear-gradient(to bottom, #bfe6ff 0%, #e3f4ff 40%, #f1fae9 62%, transparent 100%); }
.typing .g-hills { inset-inline: 0; inset-block-end: 0; block-size: 56cqb; }
.typing .g-glow { inset: 30cqb 0 0; background: radial-gradient(ellipse 55% 45% at 82% 25%, #fff6b8b0, transparent 70%); }
.typing :is(.g-sky, .g-hills, .g-glow) { opacity: 0; transition: opacity 1.2s ease; }
.typing :is(.g-sky, .g-hills, .g-glow).on { opacity: 1; }

/* 풀 · 꽃 — 뿌리(아래 가운데)를 축으로 돋아나고 바람에 흔들린다. 앞(아래)에 있는 것이 위에 그려진다 */
.typing .g-plant {
	inset-inline-start: var(--x);
	inset-block-end: var(--y);
	z-index: var(--z);
	block-size: var(--h);
	aspect-ratio: 2 / 3;
	translate: -50% 0;
	transform-origin: 50% 100%;
	scale: 0;
	opacity: 0;
	transition: scale 0.7s cubic-bezier(0.34, 1.56, 0.64, 1) var(--d), opacity 0.4s ease var(--d);
}
.typing :is(.g-grass, .g-sprout) { aspect-ratio: 1; }
.typing .g-tulip { aspect-ratio: 40 / 64; }
.typing .g-lavender { aspect-ratio: 30 / 64; }
.typing .g-cosmos { aspect-ratio: 44 / 92; }
.typing .g-plant.on { scale: 1; opacity: 1; }
.typing .g-plant.on > svg { transform-origin: 50% 100%; animation: g-sway var(--sway) ease-in-out infinite alternate; }
@keyframes g-sway { from { transform: rotate(-3deg); } to { transform: rotate(3deg); } }

/* 해 — 언덕 뒤에서 떠오른다. 정원이 다 자라면 햇살이 돈다 */
.typing .g-sun {
	inset-inline-start: 84cqi;
	inset-block-start: 36cqb;
	z-index: -1;
	block-size: 15cqb;
	aspect-ratio: 1;
	translate: -50% 0;
	opacity: 0;
	scale: 0.4;
	filter: drop-shadow(0 0 10px #fde68a);
	transition: opacity 1s ease, scale 1.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.typing .g-sun.on { opacity: 1; scale: 1; }
.typing .g-sun .sun-rays { transform-origin: 50% 50%; }
.typing .garden-scene[data-level='5'] .g-sun .sun-rays { animation: g-spin 40s linear infinite; }
@keyframes g-spin { to { transform: rotate(360deg); } }

/* 구름 — 하늘을 천천히 가로질러 흘러간다(해 앞, 언덕 뒤) */
.typing .g-cloud {
	inset-inline-start: var(--x);
	inset-block-start: var(--cy);
	z-index: -1;
	inline-size: calc(var(--s) * 13cqi);
	aspect-ratio: 2;
	opacity: 0;
	transition: opacity 1.4s ease;
}
.typing .g-cloud.on { opacity: 0.92; animation: g-drift 90s linear var(--delay) infinite; }
@keyframes g-drift {
	from { translate: calc(-1 * var(--x) - 16cqi) 0; }
	to { translate: calc(100cqi - var(--x) + 2cqi) 0; }
}

/* 나비 · 벌 — 꽃밭 위를 날아다닌다. 날지 않을 때(움직임 줄이기)는 제자리(첫 지점)에 앉아 있다 */
.typing .g-flyer { inset-block-start: 0; inset-inline-start: 0; z-index: 200; opacity: 0; transition: opacity 0.8s ease; }
.typing .g-flyer.on { opacity: 1; }
.typing .g-butterfly { inline-size: 6cqb; aspect-ratio: 40 / 32; }
.typing .g-bee { inline-size: 4.4cqb; aspect-ratio: 32 / 24; }
.typing .g-butterfly.on > svg { animation: g-flap 0.28s ease-in-out infinite alternate; }
.typing .g-bee.on .bee-wings { transform-box: fill-box; transform-origin: 50% 100%; animation: g-buzz 0.08s linear infinite alternate; }
@keyframes g-flap { to { transform: scaleX(0.35); } }
@keyframes g-buzz { to { transform: scaleY(0.55); } }
.typing .g-flyer.f1 { translate: 6cqi 52cqb; }
.typing .g-flyer.f2 { translate: 90cqi 50cqb; }
.typing .g-flyer.f3 { translate: 30cqi 46cqb; }
.typing .g-flyer.f4 { translate: 94cqi 60cqb; }
.typing .g-flyer.f5 { translate: 4cqi 70cqb; }
.typing .g-flyer.f6 { translate: 86cqi 80cqb; }
.typing .g-flyer.f7 { translate: 40cqi 48cqb; }
.typing .g-flyer.f1.on { animation: g-fly-1 16s ease-in-out infinite; }
.typing .g-flyer.f2.on { animation: g-fly-2 18s ease-in-out -4s infinite; }
.typing .g-flyer.f3.on { animation: g-fly-3 22s ease-in-out -9s infinite; }
.typing .g-flyer.f4.on { animation: g-fly-4 14s ease-in-out -2s infinite; }
.typing .g-flyer.f5.on { animation: g-fly-5 7s ease-in-out infinite; }
.typing .g-flyer.f6.on { animation: g-fly-6 8s ease-in-out -3s infinite; }
.typing .g-flyer.f7.on { animation: g-fly-7 9s ease-in-out -5s infinite; }
@keyframes g-fly-1 { 0%, 100% { translate: 6cqi 52cqb; } 20% { translate: 14cqi 44cqb; } 40% { translate: 24cqi 54cqb; } 60% { translate: 16cqi 60cqb; } 80% { translate: 9cqi 47cqb; } }
@keyframes g-fly-2 { 0%, 100% { translate: 90cqi 50cqb; } 25% { translate: 80cqi 58cqb; } 50% { translate: 70cqi 46cqb; } 75% { translate: 84cqi 44cqb; } }
@keyframes g-fly-3 { 0%, 100% { translate: 30cqi 46cqb; } 25% { translate: 45cqi 42cqb; } 50% { translate: 60cqi 50cqb; } 75% { translate: 44cqi 56cqb; } }
@keyframes g-fly-4 { 0%, 100% { translate: 94cqi 60cqb; } 30% { translate: 88cqi 70cqb; } 60% { translate: 96cqi 66cqb; } }
@keyframes g-fly-5 { 0%, 100% { translate: 4cqi 70cqb; } 20% { translate: 10cqi 76cqb; } 40% { translate: 6cqi 84cqb; } 60% { translate: 12cqi 78cqb; } 80% { translate: 8cqi 72cqb; } }
@keyframes g-fly-6 { 0%, 100% { translate: 86cqi 80cqb; } 25% { translate: 92cqi 74cqb; } 50% { translate: 96cqi 84cqb; } 75% { translate: 90cqi 88cqb; } }
@keyframes g-fly-7 { 0%, 100% { translate: 40cqi 48cqb; } 25% { translate: 52cqi 44cqb; } 50% { translate: 64cqi 50cqb; } 75% { translate: 52cqi 54cqb; } }

/* 어두운 테마 — 해 질 녘 정원(배경이 글자보다 튀지 않게 한 톤 가라앉힌다) */
.wa-dark .typing .garden-scene { opacity: 0.72; }
.wa-dark .typing .g-sky { background: linear-gradient(to bottom, #1b3558 0%, #24466b 40%, #2d4a3a 66%, transparent 100%); }

@media (max-width: 640px) {
	.typing .lesson-grid { grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); }
	.typing .pr-text .glyph { font-size: 2.2rem; }
}
@media (max-width: 520px) {
	.typing .typing-tabs { display: flex; inline-size: 100%; box-sizing: border-box; }
	.typing .typing-tabs .tab { flex: 1; justify-content: center; padding-inline: 0.55rem; font-size: 0.8rem; }
	.typing .pr-chips { flex: 1; }
	.typing .pr-chips .chip { flex: 1; }
}
@media (prefers-reduced-motion: reduce) {
	.typing .stage-wipe { animation: none; opacity: 0; }
	.typing :is(.pill.accent, .spark, .shockwave, svg.kbd .ring, svg.kbd .halo, svg.kbd .arrow, svg.hands .glow, svg.hands .reach) { animation: none; }
	.typing .fireworks { display: none; }
}

/* ── 게임 목록 — 카드는 위젯(x-typing.game-cards)이라 public/css/pages/typing-game-cards.css 에 있다 ── */

/* ── 게임 화면 ────────────────────────────────── */
.typing .game { display: flex; flex-direction: column; gap: 0.9rem; min-block-size: 26rem; }
.typing .g-intro,
.typing .g-over {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.6rem;
	padding: 2.5rem 1rem;
	text-align: center;
}
.typing .g-icon { color: var(--ty-brand); font-size: 3rem; }
.typing :is(.g-intro, .g-over) h2 { margin: 0; font-size: 1.6rem; font-weight: 800; }
.typing .g-intro p { max-inline-size: 28rem; margin: 0; color: var(--ty-muted); }
.typing .g-best { margin: 0; font-weight: 700; color: var(--ty-ink); }
.typing .g-newbest { margin: 0; font-weight: 800; color: #b45309; }
.typing .g-result { display: flex; gap: 2rem; margin-block: 0.5rem; }
.typing .g-result > div { display: flex; flex-direction: column; align-items: center; }
.typing .gr-v { font-size: 2rem; font-weight: 800; color: var(--ty-brand); }
.typing .gr-l { font-size: 0.75rem; color: var(--ty-muted); }
.typing .g-btns { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.6rem; }
.typing .g-btn {
	padding: 0.6rem 1.4rem;
	border: 1px solid var(--ty-border);
	border-radius: 999px;
	background: var(--ty-surface);
	color: var(--ty-ink);
	font-weight: 700;
	cursor: pointer;
}
.typing .g-btn.accent { border-color: transparent; background: var(--ty-brand); color: #fff; }
.typing .g-btn:hover { filter: brightness(1.05); }

.typing .g-hud { display: flex; flex-wrap: wrap; align-items: center; gap: 1.2rem; padding: 0.25rem; }
.typing .hud-life { display: flex; gap: 0.2rem; color: #ef4444; font-size: 1.2rem; }
.typing .hud-life .lost { opacity: 0.3; }
.typing .hud-time { color: var(--ty-ink); font-size: 1.5rem; font-weight: 800; transition: color 0.2s ease, transform 0.2s ease; }
.typing .hud-time.low { color: #ef4444; }
.typing .hud-time.bonus { color: #16a34a; transform: scale(1.15); }
.typing .hud-score { display: flex; flex-direction: column; }
.typing .hs-v { font-size: 1.35rem; font-weight: 800; line-height: 1; }
.typing .hs-l { font-size: 0.65rem; color: var(--ty-muted); }
.typing .hud-combo {
	margin-inline-start: auto;
	padding: 0.25rem 0.7rem;
	border-radius: 999px;
	background: linear-gradient(135deg, #6c8cff, #7aa2ff);
	color: #fff;
	font-weight: 800;
}
.typing .hud-combo[data-tier='great'] { background: linear-gradient(135deg, #16a34a, #34d399); }
.typing .hud-combo[data-tier='critical'] { background: linear-gradient(135deg, #f59e0b, #f97316); }
.typing .hud-combo[data-tier='fever'] { background: linear-gradient(135deg, #ef4444, #f43f5e); }

.typing .g-word {
	display: flex;
	flex: 1;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 0.1rem;
	padding: 2rem 1rem;
	border-radius: var(--wa-border-radius-l);
	background: var(--ty-lowered);
	font-family: var(--wa-font-family-code);
}
.typing .gw-unit { padding: 0 0.1rem; border-radius: 0.3rem; color: var(--ty-muted); font-size: 2.6rem; font-weight: 700; }
.typing .gw-unit.done { color: var(--wa-color-success-fill-loud); }
.typing .gw-unit.cur { background: var(--ty-brand); color: #fff; }

/* 단어 비 무대 — 떨어지는 단어의 자리(--x·--y)는 JS 가 매 프레임 준다 */
.typing .arena {
	position: relative;
	flex: 1;
	min-block-size: 22rem;
	overflow: hidden;
	border: 1px solid var(--ty-border);
	border-radius: var(--wa-border-radius-l);
	background: linear-gradient(180deg, color-mix(in srgb, var(--ty-brand) 10%, var(--ty-surface)) 0%, var(--ty-surface) 100%);
}
.typing .arena-field { position: absolute; inset: 0; }
.typing .floor-line {
	position: absolute;
	inset-inline: 0;
	inset-block-end: 28px;
	block-size: 2px;
	background: repeating-linear-gradient(90deg, #ef4444 0 8px, transparent 8px 16px);
	opacity: 0.6;
}
.typing .fw {
	position: absolute;
	inset-block-start: var(--y, 0);
	inset-inline-start: var(--x, 50%);
	display: flex;
	gap: 0.02rem;
	padding: 0.15rem 0.4rem;
	border: 2px solid hsl(var(--hue, 220deg) 60% 80%);
	border-radius: 0.5rem;
	background: hsl(var(--hue, 220deg) 70% 96%);
	font-family: var(--wa-font-family-code);
	white-space: nowrap;
	translate: -50% 0;
}
.typing .fw.active { border-color: var(--ty-brand); box-shadow: 0 0 0 2px color-mix(in srgb, var(--ty-brand) 30%, transparent); }
.typing .fw-ch { color: #374151; font-size: 1.3rem; font-weight: 700; }
.typing .fw-ch.done { color: #16a34a; }
.typing .fw-ch.cur { color: var(--ty-brand); text-decoration: underline; }
.typing .g-over {
	position: absolute;
	inset: 0;
	justify-content: center;
	padding: 1rem;
	background: color-mix(in srgb, var(--ty-surface) 92%, transparent);
	backdrop-filter: blur(2px);
}

/* ── 랭킹(게임 · 시험 공통) ───────────────────── */
.typing .ranking { display: flex; flex-direction: column; gap: 0.9rem; }
.typing .rk-picks { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.typing :is(.rk-pick, .rk-exam) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.35rem;
	padding: 0.55rem 0.9rem;
	border: 1px solid var(--ty-border);
	border-radius: var(--wa-border-radius-l);
	background: var(--ty-surface);
	color: var(--ty-muted);
	font-size: 0.88rem;
	font-weight: 740;
	cursor: pointer;
	transition: color var(--pes-motion), border-color var(--pes-motion), transform var(--pes-motion);
}
.typing :is(.rk-pick, .rk-exam):hover:not([aria-selected='true']) { border-color: color-mix(in srgb, var(--ty-brand) 30%, transparent); color: var(--ty-ink); transform: translateY(-1px); }
.typing :is(.rk-pick, .rk-exam)[aria-selected='true'] { border-color: transparent; background: linear-gradient(135deg, #4056b4, var(--ty-brand)); color: #fff; box-shadow: 0 9px 20px color-mix(in srgb, var(--ty-brand) 24%, transparent); }
.typing .rk-exams { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.55rem; }
.typing .rk-head { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem; }
.typing .rk-periods {
	display: inline-flex;
	align-self: flex-start;
	gap: 0.25rem;
	padding: 0.25rem;
	border: 1px solid color-mix(in srgb, var(--ty-border) 64%, transparent);
	border-radius: 999px;
	background: var(--ty-lowered);
}
.typing .rk-period { padding: 0.35rem 0.9rem; border: none; border-radius: 999px; background: transparent; color: var(--ty-muted); font-size: 0.82rem; font-weight: 740; cursor: pointer; }
.typing .rk-period[aria-selected='true'] { background: var(--ty-ink); color: var(--ty-surface); }
.typing .rk-total { margin-inline-start: auto; padding: 0.28rem 0.6rem; border-radius: 999px; background: var(--ty-lowered); color: var(--ty-muted); font-size: 0.8rem; }
.typing :is(.rk-msg, .rk-login) { margin: 0; padding-block: 1.5rem; text-align: center; color: var(--ty-muted); }
.typing .rk-login { padding-block: 0.5rem; font-size: 0.85rem; }
.typing .rk-msg.error { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 0.6rem; color: var(--wa-color-danger-on-quiet); }
.typing .rk-retry { padding: 0.3rem 0.9rem; border: 1px solid currentColor; border-radius: 999px; background: transparent; color: inherit; font-size: 0.82rem; font-weight: 700; cursor: pointer; }
.typing :is(.rk-list, .rk-table) { display: flex; flex-direction: column; gap: 0.3rem; margin: 0; padding: 0; list-style: none; transition: opacity 0.15s ease; }
.typing :is(.rk-list, .rk-table).busy { opacity: 0.55; }
.typing .rk-row {
	display: grid;
	grid-template-columns: 2.6rem minmax(0, 1fr) auto;
	align-items: center;
	gap: 0.6rem;
	padding: 0.6rem 0.9rem;
	border: 1px solid color-mix(in srgb, var(--ty-border) 82%, transparent);
	border-radius: var(--wa-border-radius-m);
	background: var(--ty-surface);
	font-size: 0.9rem;
}
.typing .rk-row.top3 { border-color: color-mix(in srgb, var(--ty-gold) 20%, transparent); background: color-mix(in srgb, var(--ty-gold) 8%, var(--ty-surface)); }
.typing .rk-row.me { border-color: var(--ty-brand); box-shadow: 0 0 0 1px var(--ty-brand); }
.typing .rk-row.fixed { margin-block-start: 0.35rem; background: color-mix(in srgb, var(--ty-brand) 12%, var(--ty-surface)); }
.typing .rk-rank { font-size: 1.05rem; font-weight: 850; text-align: center; }
.typing .rk-name { display: flex; align-items: center; gap: 0.4rem; min-inline-size: 0; overflow: hidden; font-weight: 600; white-space: nowrap; }
.typing .rk-nick { overflow: hidden; text-overflow: ellipsis; }
.typing .rk-mebadge { flex: none; padding: 0.08rem 0.42rem; border-radius: 999px; background: var(--ty-brand); color: #fff; font-size: 0.66rem; font-weight: 800; }
.typing .rk-mylabel { flex: none; color: var(--ty-brand); font-size: 0.75rem; font-weight: 700; }
.typing .rk-best { font-weight: 800; color: var(--ty-brand); }

/* ── 급수 시험 ─────────────────────────────────── */
.typing .th-hero {
	position: relative;
	display: grid;
	grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
	align-items: center;
	gap: clamp(1.5rem, 4vw, 4rem);
	min-block-size: 290px;
	margin-block-end: 1.25rem;
	overflow: hidden;
	padding: clamp(1.7rem, 4vw, 3rem);
	border: 1px solid color-mix(in srgb, var(--ty-brand) 24%, transparent);
	border-radius: 1.75rem;
	background: radial-gradient(circle at 92% 4%, rgba(255, 255, 255, 0.2), transparent 26%), linear-gradient(135deg, #29367c 0%, #526ddd 52%, #7869e8 100%);
	box-shadow: 0 24px 60px rgba(54, 71, 155, 0.2);
	color: #fff;
}
.typing .th-hero::before {
	content: '';
	position: absolute;
	inset-block-end: -8rem;
	inset-inline-end: -6rem;
	inline-size: 15rem;
	block-size: 15rem;
	border: 1px solid rgba(255, 255, 255, 0.2);
	border-radius: 999px;
	box-shadow: 0 0 0 2.5rem rgba(255, 255, 255, 0.035);
	pointer-events: none;
}
.typing :is(.hero-copy, .hero-grades) { position: relative; z-index: 1; }
.typing .hero-kicker { display: flex; align-items: center; gap: 0.55rem; margin-block-end: 0.85rem; color: rgba(255, 255, 255, 0.72); font-size: 0.72rem; font-weight: 850; letter-spacing: 0.12em; text-transform: uppercase; }
.typing .live-dot { inline-size: 0.55rem; block-size: 0.55rem; border-radius: 50%; background: #75f0ba; box-shadow: 0 0 0 0.25rem rgba(117, 240, 186, 0.16); }
.typing .th-hero h1 { max-inline-size: 14ch; margin: 0; color: #fff; font-size: clamp(2rem, 4.6vw, 3.4rem); font-weight: 900; line-height: 1.1; letter-spacing: -0.04em; }
.typing .th-hero p { max-inline-size: 36rem; margin: 1rem 0 0; color: rgba(255, 255, 255, 0.78); font-size: clamp(0.95rem, 1.4vw, 1.08rem); line-height: 1.65; }
.typing .hero-keyboard { display: flex; align-items: center; gap: 0.38rem; margin-block-start: 1.45rem; direction: ltr; }
.typing .hero-keyboard span {
	display: grid;
	place-items: center;
	inline-size: 1.9rem;
	block-size: 1.9rem;
	border: 1px solid rgba(255, 255, 255, 0.18);
	border-radius: 0.45rem;
	background: rgba(255, 255, 255, 0.09);
	box-shadow: 0 4px 0 rgba(22, 29, 77, 0.2);
	color: rgba(255, 255, 255, 0.75);
	font-size: 0.65rem;
	font-weight: 800;
}
.typing .hero-keyboard .key-space { inline-size: 4.6rem; margin-inline-start: 0.15rem; }
.typing .hero-grades {
	display: flex;
	flex-direction: column;
	gap: 0.65rem;
	padding: 0.85rem;
	border: 1px solid rgba(255, 255, 255, 0.18);
	border-radius: 1.25rem;
	background: rgba(18, 25, 71, 0.22);
	backdrop-filter: blur(12px);
}
.typing .hero-grade { display: grid; grid-template-columns: 2.65rem 1fr auto; align-items: center; gap: 0.75rem; padding: 0.65rem 0.75rem; border-radius: 0.9rem; background: rgba(255, 255, 255, 0.08); }
.typing .hg-medal {
	display: grid;
	place-items: center;
	inline-size: 2.35rem;
	block-size: 2.35rem;
	border: 1px solid rgba(255, 255, 255, 0.28);
	border-radius: 50%;
	background: linear-gradient(145deg, #ffd568, #eb9b18);
	color: #603c08;
	font-size: 0.95rem;
	font-weight: 900;
}
.typing .hero-grade[data-g='2'] .hg-medal { background: linear-gradient(145deg, #f3f7fa, #9aacc0); color: #3d4b5c; }
.typing .hero-grade[data-g='3'] .hg-medal { background: linear-gradient(145deg, #e8a875, #a96332); color: #fff; }
.typing .hg-copy { display: flex; flex-direction: column; gap: 0.12rem; min-inline-size: 0; }
.typing .hg-copy strong { font-size: 0.88rem; }
.typing .hg-copy small { overflow: hidden; color: rgba(255, 255, 255, 0.62); font-size: 0.72rem; text-overflow: ellipsis; white-space: nowrap; }
.typing .hg-acc { color: #9bf5c9; font-size: 0.78rem; font-weight: 850; }
.typing .lang-row { display: flex; justify-content: flex-end; margin-block-end: 1rem; }
.typing .lang-row .lang-picker { flex-wrap: wrap; }

.typing .th-alert {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.6rem;
	margin-block-end: 1.25rem;
	padding: 0.8rem 1rem;
	border: 1px solid color-mix(in srgb, var(--ty-brand) 55%, transparent);
	border-radius: 1rem;
	background: color-mix(in srgb, var(--ty-brand) 10%, var(--ty-surface));
}
.typing .th-alert.best { border-color: var(--ty-gold); background: color-mix(in srgb, var(--ty-gold) 14%, var(--ty-surface)); }
.typing .alert-icon { display: grid; place-items: center; inline-size: 2rem; block-size: 2rem; border-radius: 50%; background: var(--ty-brand); color: #fff; }
.typing .th-alert-grade { font-weight: 800; }
.typing .th-alert-best { font-weight: 800; color: #b45309; }

.typing .exam-section { margin-block-end: 2rem; }
.typing .section-heading { display: flex; align-items: center; gap: 0.8rem; margin-block-end: 0.9rem; }
.typing .section-icon {
	display: grid;
	place-items: center;
	inline-size: 2.6rem;
	block-size: 2.6rem;
	border-radius: 0.85rem;
	background: color-mix(in srgb, var(--ty-brand) 13%, var(--ty-surface));
	color: var(--ty-brand);
	font-size: 1.05rem;
}
.typing .section-overline { display: block; margin-block-end: 0.12rem; color: var(--ty-muted); font-size: 0.66rem; font-weight: 850; letter-spacing: 0.1em; text-transform: uppercase; }
.typing .section-heading h2 { margin: 0; font-size: 1.25rem; }

.typing .exam-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1rem; }
.typing .exam-card {
	--accent: #16a34a;
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 0.52rem;
	min-block-size: 310px;
	overflow: hidden;
	padding: 1.25rem;
	border-radius: 1.35rem;
	color: var(--ty-ink);
	text-align: start;
	cursor: pointer;
	transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
.typing .exam-card[data-exam='sentence'] { --accent: #6c8cff; }
.typing .exam-card[data-exam='long'] { --accent: #f59e0b; }
.typing .exam-card::before {
	content: '';
	position: absolute;
	inset-block-start: -5rem;
	inset-inline-end: -4rem;
	inline-size: 8rem;
	block-size: 8rem;
	border-radius: 50%;
	background: color-mix(in srgb, var(--accent) 13%, transparent);
	transition: transform 0.25s ease;
}
.typing .exam-card:hover { transform: translateY(-5px); border-color: color-mix(in srgb, var(--accent) 42%, transparent); box-shadow: var(--wa-shadow-l); }
.typing .exam-card:hover::before { transform: scale(1.25); }
.typing .ec-topline { display: flex; align-items: flex-start; justify-content: space-between; margin-block-end: 0.35rem; }
.typing .ec-icon { display: grid; place-items: center; inline-size: 3rem; block-size: 3rem; border-radius: 1rem; background: color-mix(in srgb, var(--accent) 12%, var(--ty-surface)); color: var(--accent); font-size: 1.25rem; }
.typing .ec-number { color: color-mix(in srgb, var(--accent) 60%, var(--ty-muted)); font-size: 0.72rem; font-weight: 850; letter-spacing: 0.12em; }
.typing .ec-name { font-size: 1.18rem; font-weight: 850; }
.typing .ec-desc { min-block-size: 3.9em; color: var(--ty-muted); font-size: 0.84rem; line-height: 1.55; }
.typing .ec-meta { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.typing .ec-chip { padding: 0.25rem 0.52rem; border-radius: 999px; background: var(--ty-lowered); color: var(--ty-muted); font-size: 0.7rem; font-weight: 700; }
.typing .ec-rec { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; min-block-size: 1.5rem; margin-block-start: 0.45rem; color: var(--ty-muted); font-size: 0.8rem; }
.typing .ec-rec b { color: var(--accent); font-size: 1.05rem; }
.typing .ec-rec.none { font-style: italic; }
.typing .ec-attempts { font-size: 0.72rem; }
.typing :is(.ec-grade, .rk-grade, .tt-grade) {
	padding: 0.1rem 0.5rem;
	border-radius: 999px;
	background: linear-gradient(135deg, #f5b301, #f59e0b);
	color: #fff;
	font-size: 0.72rem;
	font-style: normal;
	font-weight: 800;
	text-align: center;
}
.typing :is(.ec-grade, .rk-grade, .tt-grade)[data-g='2'] { background: linear-gradient(135deg, #94a3b8, #64748b); }
.typing :is(.ec-grade, .rk-grade, .tt-grade)[data-g='3'] { background: linear-gradient(135deg, #c08457, #a16207); }
.typing :is(.rk-grade, .tt-grade)[data-g='0'] { background: var(--ty-lowered); color: var(--ty-muted); }
.typing .ec-go {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-block-start: auto;
	padding-block-start: 0.85rem;
	border-block-start: 1px solid var(--ty-border);
	color: var(--accent);
	font-size: 0.85rem;
	font-weight: 800;
}
.typing .ec-arrow { display: grid; place-items: center; inline-size: 2rem; block-size: 2rem; border-radius: 50%; background: var(--accent); color: #fff; }

.typing .info-grid { display: grid; grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr); gap: 1rem; }
.typing :is(.info-card, .ranking-panel) {
	padding: clamp(1.1rem, 2.5vw, 1.5rem);
	border: 1px solid color-mix(in srgb, var(--ty-border) 86%, transparent);
	border-radius: 1.35rem;
	background: var(--ty-surface);
	box-shadow: var(--wa-shadow-s);
}
.typing .ranking-panel { min-block-size: 420px; }
.typing .info-title { display: flex; align-items: center; gap: 0.7rem; margin-block-end: 1rem; }
.typing .info-title h2 { margin: 0; font-size: 1rem; }
.typing .info-icon { display: grid; place-items: center; inline-size: 2.25rem; block-size: 2.25rem; border-radius: 0.75rem; background: rgba(108, 140, 255, 0.12); color: #6c8cff; }
.typing .info-icon[data-tone='mint'] { background: rgba(22, 163, 74, 0.12); color: #16a34a; }
.typing .gd-list { display: flex; flex-direction: column; gap: 0.45rem; }
.typing .gd { display: flex; align-items: center; gap: 0.7rem; padding: 0.62rem 0.7rem; border-radius: 0.85rem; background: color-mix(in srgb, var(--ty-gold) 6%, var(--ty-lowered)); }
.typing .gd[data-g='2'] { background: color-mix(in srgb, #64748b 7%, var(--ty-lowered)); }
.typing .gd[data-g='3'] { background: color-mix(in srgb, #a16207 7%, var(--ty-lowered)); }
.typing .gd[data-g='0'] { background: var(--ty-lowered); }
.typing .gd-rank { display: grid; flex: 0 0 auto; place-items: center; inline-size: 1.9rem; block-size: 1.9rem; border-radius: 50%; background: var(--ty-gold); color: #fff; font-size: 0.74rem; font-weight: 900; }
.typing .gd[data-g='2'] .gd-rank { background: #718096; }
.typing .gd[data-g='3'] .gd-rank { background: #a16207; }
.typing .gd[data-g='0'] .gd-rank { background: var(--ty-border); color: var(--ty-muted); }
.typing .gd-copy { display: flex; flex-direction: column; gap: 0.08rem; min-inline-size: 0; }
.typing .gd-name { font-size: 0.84rem; font-weight: 850; }
.typing .gd-cond { color: var(--ty-muted); font-size: 0.72rem; line-height: 1.4; }
.typing .th-notice { display: flex; align-items: flex-start; gap: 0.4rem; margin: 0.8rem 0 0; color: var(--ty-muted); font-size: 0.72rem; line-height: 1.5; }
.typing .th-formula ul { display: flex; flex-direction: column; gap: 0.5rem; margin: 0; padding: 0; list-style: none; }
.typing .th-formula li {
	display: grid;
	grid-template-columns: 2rem 1fr 2rem;
	align-items: center;
	gap: 0.65rem;
	padding-block: 0.54rem;
	border-block-end: 1px solid var(--ty-border);
	color: var(--ty-muted);
	font-size: 0.76rem;
	line-height: 1.45;
}
.typing .th-formula li:last-child { border-block-end: none; }
.typing .formula-icon { display: grid; place-items: center; inline-size: 1.9rem; block-size: 1.9rem; border-radius: 0.65rem; background: var(--ty-lowered); color: var(--ty-brand); }
.typing .th-formula li strong { display: grid; place-items: center; inline-size: 2rem; block-size: 2rem; border-radius: 50%; background: var(--ty-ink); color: var(--ty-surface); font-size: 0.72rem; }

/* 시험 랭킹 표 — 순위 | 계정 | 급수 | 타수 | 정확도 | 점수 | 시각 */
.typing .rk-table .rk-row { grid-template-columns: 2.6rem minmax(0, 1fr) 5.6rem 3.4rem 3.8rem 3.4rem 7.4rem; gap: 0.5rem; padding: 0.65rem 0.8rem; font-size: 0.88rem; }
.typing .rk-table .rk-row.head { border-color: transparent; background: transparent; color: var(--ty-muted); font-size: 0.72rem; font-weight: 700; padding-block-end: 0; }
.typing .rk-row.head .rk-grade { padding: 0; background: none; color: inherit; font-size: inherit; }
.typing .rk-grade { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.typing .rk-avatar {
	display: grid;
	flex: none;
	place-items: center;
	inline-size: 1.55rem;
	block-size: 1.55rem;
	border-radius: 50%;
	background: linear-gradient(135deg, #7c8cf8, var(--ty-brand));
	color: #fff;
	font-size: 0.72rem;
	font-weight: 800;
}
.typing .rk-lang { flex: none; padding: 0.02rem 0.35rem; border-radius: 0.35rem; background: var(--ty-lowered); color: var(--ty-muted); font-size: 0.64rem; font-weight: 700; text-transform: uppercase; }
.typing :is(.rk-cpm, .rk-acc) { color: var(--ty-muted); text-align: end; }
.typing .rk-score { color: var(--ty-brand); font-weight: 800; text-align: end; }
.typing .rk-time { overflow: hidden; color: var(--ty-muted); font-size: 0.76rem; text-align: end; text-overflow: ellipsis; white-space: nowrap; }
.typing .rk-pager { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.25rem; margin-block-start: 0.35rem; }
.typing .pg { min-inline-size: 2rem; padding: 0.35rem 0.55rem; border: 1px solid var(--ty-border); border-radius: 0.65rem; background: var(--ty-surface); color: var(--ty-muted); font-size: 0.85rem; font-weight: 760; cursor: pointer; }
.typing .pg[aria-current='page'] { border-color: transparent; background: var(--ty-brand); color: #fff; }
.typing .pg:disabled { opacity: 0.4; cursor: default; }
.typing .pg.gap { border: none; background: transparent; cursor: default; }

/* 응시 화면 */
.typing .exam-stage {
	display: flex;
	flex-direction: column;
	gap: 1rem;
	padding: clamp(1rem, 2.5vw, 1.75rem);
	border: 1px solid color-mix(in srgb, var(--ty-border) 82%, transparent);
	border-radius: 1.5rem;
	background: var(--ty-surface);
	box-shadow: var(--wa-shadow-m);
}
.typing .tt-bar { display: grid; grid-template-columns: auto minmax(8rem, 1fr) auto; align-items: center; gap: 0.75rem; }
.typing .tt-exit {
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
	padding: 0.48rem 0.8rem;
	border: 1px solid var(--ty-border);
	border-radius: 999px;
	background: var(--ty-surface);
	color: var(--ty-muted);
	font-size: 0.82rem;
	font-weight: 760;
	cursor: pointer;
}
.typing .tt-exit:hover { border-color: color-mix(in srgb, var(--ty-brand) 42%, transparent); color: var(--ty-brand); }
.typing .tt-name { display: inline-flex; align-items: center; gap: 0.5rem; font-size: 1.06rem; }
.typing .tt-live { inline-size: 0.5rem; block-size: 0.5rem; border-radius: 50%; background: #16a34a; box-shadow: 0 0 0 0.22rem rgba(22, 163, 74, 0.16); }
.typing .tt-stats { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.typing .tt-stat {
	display: flex;
	flex-direction: column;
	align-items: center;
	min-inline-size: 3.6rem;
	padding: 0.3rem 0.55rem;
	border: 1px solid var(--ty-border);
	border-radius: 0.75rem;
	background: var(--ty-lowered);
	color: var(--ty-muted);
	font-size: 0.66rem;
}
.typing .tt-stat b { color: var(--ty-ink); font-size: 1.05rem; font-variant-numeric: tabular-nums; }
.typing .tt-stat.time b { color: var(--ty-brand); }
.typing .tt-stat.time.urgent b { color: #ef4444; }
.typing .tt-timebar { block-size: 0.4rem; overflow: hidden; border-radius: 999px; background: var(--ty-lowered); }
.typing .tt-timefill { inline-size: var(--pct, 100%); block-size: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--ty-brand), #57d998); transition: inline-size 0.1s linear; }
.typing .tt-timefill.urgent { background: linear-gradient(90deg, #ef4444, #f97316); }
.typing .tt-passage-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.6rem; }
.typing .tt-title { font-size: 1.05rem; font-weight: 800; }
.typing .tt-source { color: var(--ty-muted); font-size: 0.85rem; line-height: 1.6; }
.typing .tt-text {
	position: relative;
	max-block-size: 16rem;
	overflow-y: auto;
	padding: 1.25rem 1.4rem;
	border: 1px solid var(--ty-border);
	border-radius: 1rem;
	background: var(--ty-lowered);
	font-family: var(--wa-font-family-code);
	font-size: 1.35rem;
	line-height: 1.9;
	white-space: pre-wrap;
	word-break: break-word;
}
.typing .tt-text .u.done { color: var(--wa-color-success-fill-loud); }
.typing .tt-text .u.todo { color: var(--ty-muted); }
.typing .tt-text .u.cur { border-radius: 0.2rem; background: var(--ty-brand); color: #fff; }
.typing .tt-text.shake .u.cur { background: #ef4444; animation: ty-shake 0.18s ease; }
@keyframes ty-shake { 25% { translate: -2px 0; } 75% { translate: 2px 0; } }
.typing .tt-ready { display: flex; align-items: center; justify-content: center; gap: 0.5rem; margin: 0; color: var(--ty-muted); font-size: 0.9rem; }

.typing .tt-result { display: flex; flex-direction: column; align-items: center; gap: 1rem; padding-block: 0.5rem; text-align: center; }
.typing .tt-reason { margin: 0; color: var(--ty-muted); font-weight: 700; }
.typing .tt-scorebox { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 1.2rem; }
.typing .tt-score .num { color: var(--ty-brand); font-size: 4rem; font-weight: 900; line-height: 1; }
.typing .tt-score .max { color: var(--ty-muted); font-size: 1.2rem; font-weight: 700; }
.typing .tt-grade { padding: 0.35rem 1rem; font-size: 1.1rem; }
.typing .tt-detail { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.6rem; inline-size: min(100%, 34rem); margin: 0; }
.typing .tt-detail div { padding: 0.55rem; border-radius: 0.8rem; background: var(--ty-lowered); }
.typing .tt-detail dt { color: var(--ty-muted); font-size: 0.72rem; }
.typing .tt-detail dd { margin: 0; font-size: 1.1rem; font-weight: 800; }
.typing .tt-parts { display: flex; flex-direction: column; gap: 0.45rem; inline-size: min(100%, 34rem); text-align: start; }
.typing .tt-parts h3 { margin: 0 0 0.2rem; font-size: 0.9rem; }
.typing .tt-part { display: grid; grid-template-columns: 5.5rem 1fr 5rem; align-items: center; gap: 0.6rem; font-size: 0.82rem; }
.typing .pt-bar { block-size: 0.5rem; overflow: hidden; border-radius: 999px; background: var(--ty-lowered); }
.typing .pt-bar i { display: block; inline-size: var(--pct, 0%); block-size: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--ty-brand), #57d998); }
.typing .pt-num { color: var(--ty-muted); text-align: end; font-variant-numeric: tabular-nums; }
.typing .tt-goal { margin: 0; color: var(--ty-ink); font-weight: 700; }
.typing .tt-goal.top { color: #b45309; }
.typing .tt-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.6rem; }
.typing .tt-btn {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	padding: 0.6rem 1.3rem;
	border: 1px solid var(--ty-border);
	border-radius: 999px;
	background: var(--ty-surface);
	color: var(--ty-ink);
	font-weight: 750;
	cursor: pointer;
}
.typing .tt-btn.primary { border-color: transparent; background: var(--ty-brand); color: #fff; }

@media (max-width: 820px) {
	.typing .th-hero,
	.typing .exam-grid,
	.typing .info-grid { grid-template-columns: 1fr; }
	.typing .exam-card { min-block-size: 0; }
	.typing .ec-desc { min-block-size: 0; }
	.typing .tt-bar { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
	.typing .rk-exams { gap: 0.35rem; }
	.typing .rk-exam { padding-inline: 0.45rem; font-size: 0.78rem; }
	.typing .rk-table .rk-row { grid-template-columns: 2.2rem minmax(0, 1fr) 4.8rem 3.2rem 6.6rem; gap: 0.35rem; padding-inline: 0.5rem; }
	.typing .rk-acc { display: none; }
	.typing .tt-detail { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 520px) {
	.typing .hero-keyboard span:nth-child(n + 7):not(.key-space),
	.typing .hg-acc,
	.typing .rk-cpm { display: none; }
	.typing .rk-table .rk-row { grid-template-columns: 2rem minmax(0, 1fr) 4.4rem 2.8rem; }
	/* 시각은 계정 아래로 내려 붙인다 */
	.typing .rk-table .rk-time { grid-column: 2 / -1; text-align: start; font-size: 0.7rem; }
	.typing .rk-table .rk-row.head .rk-time { display: none; }
	.typing .hub-tabs { display: flex; inline-size: 100%; }
	.typing .hub-tab { flex: 1; justify-content: center; }
	.typing .tt-part { grid-template-columns: 4.5rem 1fr 4.2rem; }
}
