/* ============================================================
   Exam Manager — Design System (Step 1 + 추천 A)
   See docs/UI 분석. 기존 .btn / .toolbar / .preview-* 등은
   하위 호환을 위해 그대로 보존하고, 신규 컴포넌트를 아래에 추가.
   ============================================================ */

/* ---------- 0. 폰트 ----------
   Pretendard Variable — 한국어 본문 가독성. SIL OFL 1.1.
   Inter — Ortto 본문/UI 영문 (Haas Grot 대체).
   Source Serif 4 — Ortto 헤드라인 (Ivar Text 대체). */
@import url("https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable.min.css");
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Source+Serif+4:ital,opsz,wght@0,8..60,400;0,8..60,600;1,8..60,400&display=swap");

/* ---------- 1. 색 팔레트 (Tailwind 정렬) ---------- */
:root {
    /* 기본 팔레트 — 브랜드는 블루마린 단일 톤, 중립은 쿨 스톤 그레이 */

    /* 블루마린 (브랜드 / primary / 액센트 — 명도차로 강약 표현) */
    --marine-50:  #eef4f9;
    --marine-100: #d4e3f0;
    --marine-200: #a7c4dc;
    --marine-300: #6f9cc0;   /* 밝은 마린 — 다크 배경 위 액센트 */
    --marine-500: #2c6f9e;   /* 중간 마린 — 포인트 */
    --marine-600: #1f5f8b;   /* primary — 흰 글씨 대비 확보 */
    --marine-700: #184c70;   /* hover / 진한 톤 */

    /* 스톤 — 쿨 중립 그레이 (slate 대체) */
    --stone-50:  #f7f9fb;
    --stone-100: #eef2f6;
    --stone-200: #dde4ec;
    --stone-300: #c4cedb;
    --stone-400: #8b97a8;
    --stone-500: #5e6b7e;
    --stone-600: #44505f;
    --stone-700: #2f3845;
    --stone-900: #161c25;

    /* 블루 — 정보(info) 상태색 전용, 브랜드 아님 */
    --blue-50:   #eff6ff;
    --blue-100:  #dbeafe;
    --blue-500:  #3b82f6;
    --blue-600:  #2563eb;
    --blue-700:  #1d4ed8;

    /* 슬레이트 — 하위호환(raw 참조용), 신규 코드는 stone 사용 */
    --slate-50:  #f8fafc;
    --slate-100: #f1f5f9;
    --slate-200: #e2e8f0;
    --slate-300: #cbd5e1;
    --slate-400: #94a3b8;
    --slate-500: #64748b;
    --slate-600: #475569;
    --slate-700: #334155;
    --slate-900: #0f172a;

    --green-50:  #f0fdf4;
    --green-100: #dcfce7;
    --green-500: #22c55e;
    --green-700: #15803d;

    --amber-50:  #fffbeb;
    --amber-100: #fef3c7;
    --amber-500: #f59e0b;
    --amber-700: #b45309;

    --red-50:    #fef2f2;
    --red-100:   #fee2e2;
    --red-500:   #ef4444;
    --red-600:   #dc2626;
    --red-700:   #b91c1c;

    /* ---------- Ortto Palette (DESIGN.md) ---------- */
    --ortto-midnight:   #14171f;   /* dark hero canvas */
    --ortto-aura:       #f9f8f7;   /* subtle surface */
    --ortto-snowdrift:  #ffffff;   /* base */
    --ortto-ink:        #000000;   /* primary text */
    --ortto-gunmetal:   #252525;   /* subhead/secondary */
    --ortto-deep:       #0d0d0d;
    --ortto-muted:      #6d6b70;   /* helper/muted */
    --ortto-porcelain:  #e9e5e2;   /* divider */
    --ortto-blue:       #1070ff;   /* single brand accent */
    --ortto-blue-hover: #0d5fd6;
    --ortto-blue-bg:    #e7f0ff;
    --ortto-violet:     #0066ff;

    /* 의미 토큰 — Ortto 톤으로 재매핑 (변수명 보존, downstream 자동 반영) */
    --c-primary:        var(--ortto-blue);
    --c-primary-hover:  var(--ortto-blue-hover);
    --c-primary-bg:     var(--ortto-blue-bg);
    --c-accent:         var(--ortto-blue);
    --c-accent-hover:   var(--ortto-blue-hover);
    --c-accent-bg:      var(--ortto-blue-bg);

    --c-success:        var(--green-700);
    --c-success-bg:     var(--green-100);
    --c-warning:        var(--amber-700);
    --c-warning-bg:     var(--amber-100);
    --c-danger:         var(--red-600);
    --c-danger-hover:   var(--red-700);
    --c-danger-bg:      var(--red-50);
    --c-info:           var(--ortto-blue);
    --c-info-bg:        var(--ortto-blue-bg);

    --c-bg:             var(--ortto-snowdrift);
    --c-surface:        var(--ortto-snowdrift);
    --c-surface-alt:    var(--ortto-aura);
    --c-fg:             var(--ortto-ink);
    --c-fg-soft:        var(--ortto-gunmetal);
    --c-muted:          var(--ortto-muted);
    --c-disabled:       #b8b4b0;
    --c-border:         var(--ortto-porcelain);
    --c-border-strong:  #d8d3cf;
    --c-error:          var(--c-danger);

    /* 스페이싱 (4px 그리드) */
    --sp-0:  0;
    --sp-1:  0.25rem;   /*  4 */
    --sp-2:  0.5rem;    /*  8 */
    --sp-3:  0.75rem;   /* 12 */
    --sp-4:  1rem;      /* 16 */
    --sp-5:  1.25rem;   /* 20 */
    --sp-6:  1.5rem;    /* 24 */
    --sp-8:  2rem;      /* 32 */
    --sp-10: 2.5rem;    /* 40 */
    --sp-12: 3rem;      /* 48 */
    --sp-16: 4rem;      /* 64 */

    /* 타이포 */
    --fs-xs:   0.75rem;   /* 12 */
    --fs-sm:   0.875rem;  /* 14 */
    --fs-base: 1rem;      /* 16 */
    --fs-lg:   1.125rem;  /* 18 */
    --fs-xl:   1.25rem;   /* 20 */
    --fs-2xl:  1.5rem;    /* 24 */
    --fs-3xl:  1.875rem;  /* 30 */
    --lh-tight:   1.25;
    --lh-normal:  1.5;
    --lh-relaxed: 1.6;
    --fw-normal: 400;
    --fw-medium: 500;
    --fw-semi:   600;
    --fw-bold:   700;

    /* 그림자 — 쿨 톤 */
    --shadow-xs: 0 1px 1px rgba(15, 23, 42, 0.04);
    --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06), 0 1px 3px rgba(15, 23, 42, 0.04);
    --shadow-md: 0 4px 12px rgba(15, 23, 42, 0.08);
    --shadow-lg: 0 12px 32px rgba(15, 23, 42, 0.12);

    /* 모서리 — Ortto 명세: tags 50px, buttons 40px, sections 16px, default 4px */
    --r-sm:   4px;
    --r-md:   6px;
    --r-lg:   8px;
    --r-xl:   12px;
    --r-pill: 999px;
    --r-tag:     50px;   /* Ortto badges/tags */
    --r-button:  40px;   /* Ortto primary/secondary buttons (pill) */
    --r-section: 16px;   /* Ortto cards/sections */

    /* Z-index */
    --z-dropdown: 100;
    --z-sticky:   150;
    --z-modal:    200;
    --z-toast:    300;

    /* 포커스 ring */
    --focus-ring: 0 0 0 3px rgba(31, 95, 139, 0.38);
    --focus-ring-danger: 0 0 0 3px rgba(220, 38, 38, 0.35);

    /* 전환 */
    --t-fast: 120ms ease;
    --t-base: 200ms ease;

    /* 폰트 패밀리 — Ortto 매핑: Inter(본문/UI), Source Serif(헤드라인 임팩트) */
    --ff-sans: "Inter", "Pretendard Variable", Pretendard,
               -apple-system, BlinkMacSystemFont, "Segoe UI", "Apple SD Gothic Neo",
               "Noto Sans KR", sans-serif;
    --ff-mono: "JetBrains Mono", "SF Mono", ui-monospace, SFMono-Regular,
               Menlo, Consolas, monospace;
    --ff-serif: "Source Serif 4", "Source Serif Pro", "Ivar Text",
                "Noto Serif KR", Georgia, serif;
    --ff-display: var(--ff-serif);

    /* Ortto display 스케일 */
    --fs-display: 4rem;     /* 64px */
    --fs-headline: 3rem;    /* 48px */

    /* Ortto card shadow — 다단 부드러운 elevation */
    --shadow-card:
        rgba(0, 0, 0, 0.04) 0 4px 4px 0,
        rgba(0, 0, 0, 0.05) 0 12px 12px 0,
        rgba(0, 0, 0, 0.06) 0 24px 24px 0,
        rgba(0, 0, 0, 0.07) 0 50px 50px 0,
        rgba(0, 0, 0, 0.08) 0 0 0 1px;
}

/* code / pre 기본 톤 */
code, kbd, samp, pre { font-family: var(--ff-mono); font-size: 0.95em; }
code { background: var(--slate-100); padding: 0.1em 0.4em; border-radius: var(--r-sm); }
pre  { background: var(--slate-100); padding: var(--sp-3); border-radius: var(--r-md); overflow: auto; }
pre code { background: transparent; padding: 0; }

* { box-sizing: border-box; }

/* HTML hidden 속성은 항상 우선. .banner 등 display 를 지정한 클래스가
   [hidden] 을 덮어쓰지 않도록 강제 (동일 명시도라 author CSS 가 이김). */
[hidden] { display: none !important; }

html, body {
    margin: 0;
    background: var(--c-bg);
    color: var(--c-fg);
    font-family: var(--ff-sans);
    font-feature-settings: "ss06", "ss10"; /* Pretendard 한국어 조판 옵션 */
    font-size: var(--fs-base);
    line-height: var(--lh-relaxed);
    text-rendering: optimizeLegibility;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    /* 한국어 — 단어 중간 줄바꿈 방지. 끊을 수 없는 긴 문자열만 fallback 으로 절단 */
    word-break: keep-all;
    overflow-wrap: break-word;
}

/* 부드러운 앵커 스크롤 — 모션 민감 사용자는 제외 */
@media (prefers-reduced-motion: no-preference) {
    html { scroll-behavior: smooth; }
}

/* 접근성 — 키보드 포커스 가시화 */
:focus-visible {
    outline: none;
    box-shadow: var(--focus-ring);
    border-radius: var(--r-sm);
}

/* ============================================================
   2. 레거시 컴포넌트 — 기존 화면 호환 (절대 변경 금지)
   ============================================================ */

.container {
    max-width: 960px;
    margin: 0 auto;
    padding: 1.5rem 1rem;
}

.topbar {
    background: #fff;
    border-bottom: 1px solid var(--c-border);
}
.topbar-inner {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.75rem 1rem;
}
.topbar .brand {
    font-weight: 800;
    font-size: var(--fs-3xl);
    letter-spacing: -0.02em;
    color: var(--c-fg);
    text-decoration: none;
}
.topbar .spacer { flex: 1; }
.topbar .auth-area { display: flex; align-items: center; gap: 0.5rem; }
.topbar .user-name { color: var(--c-muted); }
.topbar .inline-form { display: inline; }

.btn {
    display: inline-block;
    padding: 0.55rem 1.4rem;
    border-radius: var(--r-button);
    border: 1px solid transparent;
    background: transparent;
    text-decoration: none;
    cursor: pointer;
    font: inherit;
    font-weight: var(--fw-medium);
    transition: background var(--t-fast), color var(--t-fast),
                border-color var(--t-fast), transform var(--t-fast);
}
/* 눌림 피드백 — 비활성 버튼은 제외 */
.btn:active:not(:disabled) { transform: scale(0.98); }
.btn-primary {
    background: var(--c-primary);
    color: #fff;
}
.btn-primary:hover { background: var(--c-primary-hover); }
.btn-link {
    color: var(--c-primary);
    background: transparent;
}
.btn-link:hover { color: var(--c-primary-hover); text-decoration: underline; }
.btn:disabled { opacity: 0.6; cursor: not-allowed; }

.auth-form { max-width: 380px; margin: 2rem auto; }
.auth-form .page-header { padding-bottom: var(--sp-3); margin-bottom: var(--sp-4); }
.auth-form .page-title  { font-size: var(--fs-2xl); }
.auth-form .form-row    { margin-bottom: var(--sp-3); }
.auth-form .btn-primary { width: 100%; padding: 0.65rem 0.9rem; font-weight: var(--fw-semi); }
.auth-form .form-hint   { font-size: var(--fs-sm); color: var(--c-muted); text-align: center; margin-top: var(--sp-4); }
.auth-form .form-hint a { color: var(--c-primary); font-weight: var(--fw-medium); text-decoration: none; }
.auth-form .form-hint a:hover { text-decoration: underline; }
.form-row { margin-bottom: 1rem; display: flex; flex-direction: column; gap: 0.25rem; }
.form-row input,
.form-row select,
.form-row textarea {
    padding: 0.55rem 0.7rem;
    border: 1px solid var(--c-border);
    border-radius: 6px;
    font: inherit;
    background: #fff;
    color: inherit;
    transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.form-row input:focus-visible,
.form-row select:focus-visible,
.form-row textarea:focus-visible {
    border-color: var(--c-primary);
    box-shadow: var(--focus-ring);
    outline: none;
}
.form-row textarea { line-height: var(--lh-normal); resize: vertical; }
.error { color: var(--c-error); }
.muted { color: var(--c-muted); }

.site-footer {
    border-top: 1px solid var(--c-border);
    padding: 1.5rem 0;
    color: var(--c-muted);
    text-align: center;
    margin-top: 3rem;
}

/* preview cards — 기존 동작 그대로 */
.preview-card {
    background: #fff;
    border: 1px solid var(--c-border);
    border-radius: 8px;
    padding: 1.25rem 1.5rem;
    margin-bottom: 1rem;
}
.preview-meta { color: var(--c-muted); font-size: 0.85rem; margin-bottom: 0.5rem; }
.preview-question { font-size: 1rem; line-height: 1.5; }
.preview-question a { color: var(--c-fg); text-decoration: none; }
.preview-question a:hover { text-decoration: underline; }
.preview-choices { list-style: none; padding-left: 0; }
.preview-choices li { padding: 0.25rem 0; color: #475569; font-size: 0.95rem; }
.choices-detail { list-style: decimal; padding-left: 1.5rem; }
.choices-detail li { padding: 0.35rem 0; }
.preview-mask {
    border-top: 1px dashed var(--c-border);
    margin-top: 1rem;
    padding-top: 1rem;
}
.preview-detail h2 { line-height: 1.5; }
.toolbar { display: flex; align-items: center; gap: 0.5rem; }
.toolbar .spacer { flex: 1; }
.inline-form { display: inline; }

/* ============================================================
   3. 신규 — 레이아웃 유틸 (opt-in: 페이지가 명시적으로 사용)
   ============================================================ */

/* 수직 stack — 자식 사이 일관 간격. .stack-{n} 으로 간격 조절 */
.stack > * + * { margin-top: var(--sp-4); }
.stack-2 > * + * { margin-top: var(--sp-2); }
.stack-3 > * + * { margin-top: var(--sp-3); }
.stack-4 > * + * { margin-top: var(--sp-4); }
.stack-6 > * + * { margin-top: var(--sp-6); }
.stack-8 > * + * { margin-top: var(--sp-8); }

/* 수평 cluster — wrap 되는 인라인 그룹 (버튼 묶음 등) */
.cluster {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
    align-items: center;
}
.cluster-end { justify-content: flex-end; }
.cluster-between { justify-content: space-between; }

/* center 콘텐츠 폭 */
.prose { max-width: 65ch; }

/* ============================================================
   4. 신규 — 페이지 헤더 / 브레드크럼
   ============================================================ */

.page-header {
    display: flex;
    align-items: flex-end;
    gap: var(--sp-4);
    margin-bottom: var(--sp-6);
    padding-bottom: var(--sp-4);
    border-bottom: 1px solid var(--c-border);
    flex-wrap: wrap;
}
.page-header-text { flex: 1; min-width: 0; }
.page-title {
    margin: 0;
    font-size: var(--fs-2xl);
    line-height: var(--lh-tight);
    font-weight: var(--fw-semi);
    letter-spacing: -0.01em;
    text-wrap: balance; /* 끝줄 한 단어 고립 방지 */
}
.page-subtitle {
    margin: var(--sp-1) 0 0;
    color: var(--c-muted);
    font-size: var(--fs-sm);
}
.page-actions {
    display: flex;
    gap: var(--sp-2);
    flex-wrap: wrap;
}

.breadcrumb {
    font-size: var(--fs-sm);
    color: var(--c-muted);
    margin-bottom: var(--sp-3);
}
.breadcrumb ol {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-1);
}
.breadcrumb li { display: flex; align-items: center; gap: var(--sp-1); }
.breadcrumb li + li::before {
    content: "›";
    color: var(--c-border-strong);
    padding: 0 var(--sp-1);
}
.breadcrumb a { color: var(--c-muted); text-decoration: none; }
.breadcrumb a:hover { color: var(--c-primary); text-decoration: underline; }
.breadcrumb [aria-current="page"] { color: var(--c-fg); font-weight: var(--fw-medium); }

/* ============================================================
   5. 신규 — Card (의미적 컨테이너)
   ============================================================ */

.card {
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--r-section);
    box-shadow: var(--shadow-xs);
    overflow: hidden;
}
.card-hover { transition: box-shadow var(--t-base), transform var(--t-base); }
.card-hover:hover { box-shadow: var(--shadow-md); transform: translateY(-1px); }

.card-header {
    padding: var(--sp-4) var(--sp-5);
    border-bottom: 1px solid var(--c-border);
    display: flex;
    align-items: center;
    gap: var(--sp-3);
}
.card-header h3 { margin: 0; font-size: var(--fs-lg); font-weight: var(--fw-semi); }
.card-body { padding: var(--sp-5); }
.card-footer {
    padding: var(--sp-3) var(--sp-5);
    border-top: 1px solid var(--c-border);
    background: var(--c-surface-alt);
    display: flex;
    align-items: center;
    gap: var(--sp-2);
}

/* 위계 변형: 위험·정보·성공 카드 (좌측 액센트 띠) */
.card-accent-danger  { border-left: 3px solid var(--c-danger); }
.card-accent-warning { border-left: 3px solid var(--c-warning); }
.card-accent-info    { border-left: 3px solid var(--c-info); }
.card-accent-success { border-left: 3px solid var(--c-success); }

/* ============================================================
   6. 신규 — Button 변형
   ============================================================ */

/* 사이즈 변형 */
.btn-sm { padding: 0.3rem 0.65rem; font-size: var(--fs-sm); }
.btn-lg { padding: 0.65rem 1.25rem; font-size: var(--fs-lg); }

/* 보조 — 1차 액션 옆에 두는 무채색 outline */
.btn-secondary {
    background: var(--c-surface);
    color: var(--c-fg);
    border-color: var(--c-border-strong);
}
.btn-secondary:hover { background: var(--c-surface-alt); border-color: var(--c-muted); }

/* 위험 (탈퇴/삭제) */
.btn-danger {
    background: var(--c-danger);
    color: #fff;
}
.btn-danger:hover { background: var(--c-danger-hover); }
.btn-danger:focus-visible { box-shadow: var(--focus-ring-danger); }
.btn-danger-ghost {
    background: transparent;
    color: var(--c-danger);
    border-color: transparent;
}
.btn-danger-ghost:hover { background: var(--c-danger-bg); }

/* Ghost (배경 없이 hover 시만) */
.btn-ghost {
    background: transparent;
    color: var(--c-fg-soft);
    border-color: transparent;
}
.btn-ghost:hover { background: var(--c-surface-alt); color: var(--c-fg); }

/* Icon 전용 — 정사각 hit area, 텍스트 대신 SVG/이모지 1자 */
.btn-icon {
    width: 2rem;
    height: 2rem;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--r-md);
}
.btn-icon.btn-sm { width: 1.625rem; height: 1.625rem; font-size: var(--fs-sm); }

/* 버튼 그룹 — 연결된 액션 묶음 */
.btn-group { display: inline-flex; gap: 0; }
.btn-group .btn {
    border-radius: 0;
    border: 1px solid var(--c-border-strong);
    margin-left: -1px;
}
.btn-group .btn:first-child { border-top-left-radius: var(--r-md); border-bottom-left-radius: var(--r-md); margin-left: 0; }
.btn-group .btn:last-child  { border-top-right-radius: var(--r-md); border-bottom-right-radius: var(--r-md); }

/* ============================================================
   7. 신규 — Form 통합 (opt-in 클래스)
   .form-row 와는 별도 — 새 페이지부터 채택
   ============================================================ */

.field {
    display: flex;
    flex-direction: column;
    gap: var(--sp-1);
    margin-bottom: var(--sp-4);
}
.field-label {
    font-size: var(--fs-sm);
    font-weight: var(--fw-medium);
    color: var(--c-fg-soft);
}
.field-hint { font-size: var(--fs-xs); color: var(--c-muted); }
.field-error { font-size: var(--fs-xs); color: var(--c-error); }

.input, .select, .textarea {
    padding: 0.55rem 0.75rem;
    border: 1px solid var(--c-border);
    border-radius: var(--r-md);
    font: inherit;
    background: var(--c-surface);
    color: inherit;
    transition: border-color var(--t-fast), box-shadow var(--t-fast);
    width: 100%;
}
.input:focus-visible,
.select:focus-visible,
.textarea:focus-visible {
    border-color: var(--c-primary);
    box-shadow: var(--focus-ring);
    outline: none;
}
.textarea { resize: vertical; line-height: var(--lh-normal); min-height: 6rem; }

.input-group { display: flex; align-items: stretch; gap: var(--sp-2); }
.input-group > * { flex: 1; }

.checkbox, .radio {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    cursor: pointer;
    user-select: none;
    font-size: var(--fs-sm);
}

.form-actions {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    padding-top: var(--sp-4);
    margin-top: var(--sp-4);
    border-top: 1px solid var(--c-border);
}
.form-actions .spacer { flex: 1; }

/* ============================================================
   8. 신규 — Badge / Tag (기존 .badge.active/.inactive 는 보존)
   ============================================================ */

/* 의미 변형 — 새 클래스. 기존 active/inactive 와 공존 */
.badge-success {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: var(--r-pill);
    font-size: var(--fs-xs);
    font-weight: var(--fw-semi);
    background: var(--c-success-bg);
    color: var(--c-success);
}
.badge-warning {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: var(--r-pill);
    font-size: var(--fs-xs);
    font-weight: var(--fw-semi);
    background: var(--c-warning-bg);
    color: var(--c-warning);
}
.badge-danger {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: var(--r-pill);
    font-size: var(--fs-xs);
    font-weight: var(--fw-semi);
    background: var(--c-danger-bg);
    color: var(--c-danger);
}
.badge-info {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: var(--r-pill);
    font-size: var(--fs-xs);
    font-weight: var(--fw-semi);
    background: var(--c-info-bg);
    color: var(--c-info);
}
.badge-neutral {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: var(--r-pill);
    font-size: var(--fs-xs);
    font-weight: var(--fw-semi);
    background: var(--slate-100);
    color: var(--slate-700);
}

/* ============================================================
   9. 신규 — Empty state / Skeleton 로딩
   ============================================================ */

.empty-state {
    text-align: center;
    padding: var(--sp-12) var(--sp-6);
    border: 1px dashed var(--c-border);
    border-radius: var(--r-section);
    background: var(--c-surface);
    color: var(--c-muted);
}
.empty-icon {
    font-size: var(--fs-3xl);
    line-height: 1;
    margin-bottom: var(--sp-3);
    opacity: 0.6;
}
.empty-title {
    color: var(--c-fg);
    font-size: var(--fs-lg);
    font-weight: var(--fw-semi);
    margin: 0 0 var(--sp-2);
}
.empty-message { margin: 0 auto var(--sp-4); max-width: 32rem; }

.skeleton {
    background: linear-gradient(90deg,
        var(--slate-100) 0%,
        var(--slate-200) 50%,
        var(--slate-100) 100%);
    background-size: 200% 100%;
    animation: skeleton-shimmer 1.2s linear infinite;
    border-radius: var(--r-md);
}
.skeleton-line { height: 0.85rem; margin-bottom: var(--sp-2); }
.skeleton-line.short { width: 60%; }
.skeleton-line.long  { width: 92%; }
.skeleton-block { height: 6rem; }
@keyframes skeleton-shimmer {
    0%   { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}

/* ============================================================
   10. 신규 — Alert / Banner (페이지 상단 안내)
   ============================================================ */

/* 문제설명(지문) — 발문 아래 결합 렌더 (docs: 문제설명 복원) */
.q-passage {
    margin-top: var(--sp-2);
    padding: var(--sp-2) var(--sp-3);
    background: var(--c-surface-alt);
    border-left: 3px solid var(--c-border-strong);
    border-radius: var(--r-sm);
}

/* 인앱 알림 — 헤더 벨 + 드롭다운 (P2, docs/25) */
.noti-menu { position: relative; }
.noti-trigger {
    position: relative; background: none; border: none; cursor: pointer;
    font-size: 1.15rem; padding: 0.3rem 0.4rem; line-height: 1;
}
.noti-badge {
    position: absolute; top: 0; right: 0;
    background: var(--c-danger); color: #fff;
    font-size: 0.65rem; font-weight: 700; line-height: 1;
    min-width: 1rem; height: 1rem; padding: 0 0.2rem;
    border-radius: 999px;
    display: flex; align-items: center; justify-content: center;
}
.noti-panel {
    position: absolute; right: 0; top: 100%; margin-top: 0.4rem;
    width: 320px; max-height: 420px; overflow-y: auto;
    background: var(--c-surface); border: 1px solid var(--c-border);
    border-radius: var(--r-md); box-shadow: 0 8px 24px rgba(0,0,0,.12);
    z-index: var(--z-dropdown);
}
.noti-panel-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 0.4rem 0.8rem; border-bottom: 1px solid var(--c-border);
    font-weight: var(--fw-semi);
}
.noti-item {
    display: block; padding: 0.6rem 0.8rem;
    border-bottom: 1px solid var(--c-border);
    text-decoration: none; color: inherit;
}
.noti-item:last-child { border-bottom: none; }
.noti-item:hover { background: var(--c-surface-alt); }
.noti-item.is-unread { background: var(--c-primary-bg); }
.noti-item .nt-title { font-weight: var(--fw-semi); font-size: 0.88rem; }
.noti-item .nt-body { font-size: 0.82rem; color: var(--c-muted); margin-top: 2px; }
.noti-item .nt-time { font-size: 0.72rem; color: var(--c-muted); margin-top: 3px; }

.banner {
    display: flex;
    gap: var(--sp-3);
    align-items: flex-start;
    padding: var(--sp-3) var(--sp-4);
    border-radius: var(--r-md);
    border: 1px solid var(--c-border);
    background: var(--c-surface);
    font-size: var(--fs-sm);
}
.banner-info    { background: var(--c-info-bg);    border-color: var(--blue-100);  color: var(--c-info); }
.banner-success { background: var(--c-success-bg); border-color: var(--green-100); color: var(--c-success); }
.banner-warning { background: var(--c-warning-bg); border-color: var(--amber-100); color: var(--c-warning); }
.banner-danger  { background: var(--c-danger-bg);  border-color: var(--red-100);   color: var(--c-danger); }

/* ============================================================
   11b. 신규 — Topbar 네비 / User menu / 모바일 햄버거
   (기존 .topbar / .topbar-inner / .brand / .spacer 는 보존)
   ============================================================ */

.topbar-inner { gap: var(--sp-3); }

.nav-toggle {
    display: none;
    background: transparent;
    border: 1px solid var(--c-border);
    border-radius: var(--r-md);
    padding: var(--sp-1) var(--sp-2);
    font-size: var(--fs-lg);
    cursor: pointer;
    color: var(--c-fg-soft);
    line-height: 1;
}

.topbar-nav {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    align-items: center;
    gap: var(--sp-1);
}
.topbar-nav a {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    padding: var(--sp-2) var(--sp-3);
    border-radius: var(--r-sm);
    color: var(--c-fg);
    text-decoration: none;
    font-size: var(--fs-base);
    font-weight: var(--fw-medium);
    border-bottom: 4px solid transparent;   /* Ortto: 4px bottom accent */
    transition: color var(--t-fast), border-color var(--t-fast);
}
.topbar-nav a:hover { color: var(--c-primary); }
.topbar-nav a.is-active {
    color: var(--c-ink, var(--c-fg));
    background: transparent;
    border-bottom-color: var(--c-primary);
}

.user-menu { position: relative; }
.user-menu-trigger {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-1) var(--sp-2);
    border: 1px solid transparent;
    background: transparent;
    border-radius: var(--r-md);
    font: inherit;
    color: var(--c-fg);
    cursor: pointer;
}
.user-menu-trigger:hover { background: var(--c-surface-alt); }
.user-menu-trigger .avatar {
    width: 1.75rem; height: 1.75rem;
    border-radius: var(--r-pill);
    background: var(--c-primary-bg);
    color: var(--c-primary);
    display: inline-flex; align-items: center; justify-content: center;
    font-weight: var(--fw-semi);
    font-size: var(--fs-sm);
}
.user-menu-trigger .caret {
    font-size: var(--fs-xs);
    color: var(--c-muted);
    transition: transform var(--t-fast);
}
.user-menu.is-open .user-menu-trigger { background: var(--c-surface-alt); }
.user-menu.is-open .caret { transform: rotate(180deg); }

.user-menu-panel {
    position: absolute;
    top: calc(100% + var(--sp-1));
    right: 0;
    min-width: 13rem;
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-lg);
    padding: var(--sp-2);
    display: none;
    z-index: var(--z-dropdown);
}
.user-menu.is-open .user-menu-panel { display: block; }

.user-menu-header {
    padding: var(--sp-2) var(--sp-3);
    border-bottom: 1px solid var(--c-border);
    margin-bottom: var(--sp-1);
}
.user-menu-header .name { font-weight: var(--fw-semi); }
.user-menu-header .role { color: var(--c-muted); font-size: var(--fs-xs); }

.user-menu-panel a, .user-menu-panel button {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    width: 100%;
    text-align: left;
    padding: var(--sp-2) var(--sp-3);
    color: var(--c-fg);
    text-decoration: none;
    background: transparent;
    border: 0;
    border-radius: var(--r-md);
    font: inherit;
    cursor: pointer;
}
.user-menu-panel a:hover, .user-menu-panel button:hover {
    background: var(--c-surface-alt);
}
.user-menu-panel .danger { color: var(--c-danger); }
.user-menu-panel .danger:hover { background: var(--c-danger-bg); }
.user-menu-divider {
    height: 1px;
    background: var(--c-border);
    margin: var(--sp-1) 0;
}

/* 모바일 — 메뉴는 토글로 펼침, 드롭다운은 전폭으로 */
@media (max-width: 768px) {
    .nav-toggle { display: inline-flex; align-items: center; }
    .topbar-nav {
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        background: var(--c-surface);
        border-bottom: 1px solid var(--c-border);
        box-shadow: var(--shadow-md);
        flex-direction: column;
        align-items: stretch;
        padding: var(--sp-2);
        gap: var(--sp-1);
        display: none;
        z-index: var(--z-dropdown);
    }
    .topbar-nav.is-open { display: flex; }
    .topbar-nav a { padding: var(--sp-3); border-radius: var(--r-md); }
    .topbar { position: relative; }
    .topbar-inner { flex-wrap: wrap; }
    .user-menu-trigger .user-name { display: none; }
}

/* ============================================================
   11c. 신규 — 마이페이지 / 정보 그리드 / 액션 카드
   ============================================================ */

/* 라벨–값 정의 리스트 (내 정보 카드 안에서 사용) */
.info-grid {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: var(--sp-2) var(--sp-4);
    margin: 0;
}
.info-grid dt {
    color: var(--c-muted);
    font-size: var(--fs-sm);
    align-self: center;
}
.info-grid dd {
    margin: 0;
    color: var(--c-fg);
    font-weight: var(--fw-medium);
    word-break: break-all;
}

/* 액션 카드 — 학습 도구처럼 큰 클릭 영역 */
.action-card {
    display: flex;
    gap: var(--sp-3);
    align-items: flex-start;
    padding: var(--sp-4);
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--r-section);
    text-decoration: none;
    color: inherit;
    transition: border-color var(--t-fast), box-shadow var(--t-fast), transform var(--t-fast);
}
.action-card:hover {
    border-color: var(--c-primary);
    box-shadow: var(--shadow-md);
    transform: translateY(-1px);
}
.action-card-icon {
    width: 2.25rem;
    height: 2.25rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--c-primary-bg);
    color: var(--c-primary);
    border-radius: var(--r-md);
    font-size: var(--fs-lg);
    flex: 0 0 auto;
}
.action-card-text { flex: 1; min-width: 0; }
.action-card-title {
    margin: 0 0 var(--sp-1);
    font-size: var(--fs-base);
    font-weight: var(--fw-semi);
}
.action-card-desc {
    margin: 0;
    color: var(--c-muted);
    font-size: var(--fs-sm);
    line-height: var(--lh-normal);
}

/* 2-3 컬럼 그리드 — 마이페이지의 상단 정보+학습 영역 */
.split-2 {
    display: grid;
    grid-template-columns: minmax(260px, 1fr) 2fr;
    gap: var(--sp-4);
}
.split-3 {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: var(--sp-3);
}
@media (max-width: 768px) {
    .split-2 { grid-template-columns: 1fr; }
}

/* ============================================================
   11e. 신규 — 유틸리티 클래스 (인라인 style 제거용)
   ============================================================ */

/* 타이포 */
.text-xs    { font-size: var(--fs-xs); }
.text-sm    { font-size: var(--fs-sm); }
.text-base  { font-size: var(--fs-base); }
.text-lg    { font-size: var(--fs-lg); }
.text-xl    { font-size: var(--fs-xl); }
.font-medium { font-weight: var(--fw-medium); }
.font-semi   { font-weight: var(--fw-semi); }
.font-bold   { font-weight: var(--fw-bold); }
.text-center { text-align: center; }
.text-right  { text-align: right; }

/* 색 */
.text-muted   { color: var(--c-muted); }
.text-danger  { color: var(--c-danger); }
.text-success { color: var(--c-success); }
.text-primary { color: var(--c-primary); }

/* margin */
.m-0  { margin: 0; }
.mt-0 { margin-top: 0; }
.mt-1 { margin-top: var(--sp-1); }
.mt-2 { margin-top: var(--sp-2); }
.mt-3 { margin-top: var(--sp-3); }
.mt-4 { margin-top: var(--sp-4); }
.mt-5 { margin-top: var(--sp-5); }
.mt-6 { margin-top: var(--sp-6); }
.mt-8 { margin-top: var(--sp-8); }
.mb-0 { margin-bottom: 0; }
.mb-1 { margin-bottom: var(--sp-1); }
.mb-2 { margin-bottom: var(--sp-2); }
.mb-3 { margin-bottom: var(--sp-3); }
.mb-4 { margin-bottom: var(--sp-4); }
.mb-6 { margin-bottom: var(--sp-6); }
.ml-1 { margin-left: var(--sp-1); }
.ml-2 { margin-left: var(--sp-2); }
.ml-3 { margin-left: var(--sp-3); }
.ml-4 { margin-left: var(--sp-4); }
.ml-auto { margin-left: auto; }
.mr-1 { margin-right: var(--sp-1); }
.mr-2 { margin-right: var(--sp-2); }
.mr-3 { margin-right: var(--sp-3); }
.mr-4 { margin-right: var(--sp-4); }
.mr-auto { margin-right: auto; }

/* padding */
.p-0 { padding: 0; }
.p-2 { padding: var(--sp-2); }
.p-3 { padding: var(--sp-3); }
.p-4 { padding: var(--sp-4); }
.p-6 { padding: var(--sp-6); }
.py-2 { padding-top: var(--sp-2); padding-bottom: var(--sp-2); }
.py-4 { padding-top: var(--sp-4); padding-bottom: var(--sp-4); }
.px-3 { padding-left: var(--sp-3); padding-right: var(--sp-3); }
.px-4 { padding-left: var(--sp-4); padding-right: var(--sp-4); }

/* flex */
.flex     { display: flex; }
.inline-flex { display: inline-flex; }
.flex-1   { flex: 1; }
.flex-wrap { flex-wrap: wrap; }
.items-center { align-items: center; }
.items-baseline { align-items: baseline; }
.items-end    { align-items: flex-end; }
.justify-end { justify-content: flex-end; }
.justify-between { justify-content: space-between; }
.gap-1 { gap: var(--sp-1); }
.gap-2 { gap: var(--sp-2); }
.gap-3 { gap: var(--sp-3); }
.gap-4 { gap: var(--sp-4); }

/* width */
.w-full   { width: 100%; }
.max-w-md { max-width: 560px; }
.max-w-lg { max-width: 720px; }
.max-w-xl { max-width: 880px; }

/* hidden helper */
.hidden { display: none; }

/* ============================================================
   11d. 신규 — 아이콘 시스템 (SVG sprite)
   ============================================================ */
.icon {
    display: inline-block;
    width: 1em;
    height: 1em;
    vertical-align: -0.15em;
    fill: none;
    stroke: currentColor;
    flex: 0 0 auto;
}
.icon-lg { width: 1.25em; height: 1.25em; }
.icon-xl { width: 1.75em; height: 1.75em; }

/* ============================================================
   11h. 신규 — 응시 타이머 + 문항 네비게이터 (Recommended-A §5)
   ============================================================ */

/* ── 타이머 — 잔여 시간 표시. JS 가 .is-warn / .is-danger 토글 ── */
.exam-timer {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-2) var(--sp-3);
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--r-md);
    font-variant-numeric: tabular-nums;
    font-weight: var(--fw-semi);
    font-size: var(--fs-lg);
    transition: background var(--t-base), border-color var(--t-base), color var(--t-base);
}
.exam-timer-label {
    font-size: var(--fs-xs);
    font-weight: var(--fw-normal);
    color: var(--c-muted);
    letter-spacing: 0.02em;
}
.exam-timer-value { color: var(--c-fg); }
.exam-timer-icon { width: 1rem; height: 1rem; color: var(--c-muted); }

/* 5분 이하 — 노랑 */
.exam-timer.is-warn {
    background: var(--c-warning-bg);
    border-color: var(--c-warning);
}
.exam-timer.is-warn .exam-timer-value,
.exam-timer.is-warn .exam-timer-icon { color: var(--c-warning); }

/* 1분 이하 — 빨강 (깜빡임 없이 정적) */
.exam-timer.is-danger {
    background: var(--c-danger-bg);
    border-color: var(--c-danger);
}
.exam-timer.is-danger .exam-timer-value,
.exam-timer.is-danger .exam-timer-icon { color: var(--c-danger); }

/* sticky 변형 — 상단 고정 */
.exam-timer-sticky {
    position: sticky;
    top: var(--sp-2);
    z-index: var(--z-sticky);
}

/* ── 문항 네비게이터 — 그리드. 1..N 번호 + 4상태 ── */
.q-nav {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(2.5rem, 1fr));
    gap: var(--sp-1);
    padding: var(--sp-3);
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--r-md);
}

.q-nav-item {
    aspect-ratio: 1 / 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--c-border);
    border-radius: var(--r-sm);
    background: var(--c-surface);
    color: var(--c-fg-soft);
    font-size: var(--fs-sm);
    font-weight: var(--fw-medium);
    text-decoration: none;
    cursor: pointer;
    position: relative;
    transition: background var(--t-fast), border-color var(--t-fast), transform var(--t-fast);
}
.q-nav-item:hover { transform: translateY(-1px); border-color: var(--c-border-strong); }

/* 상태:
   .is-answered  답안 입력됨        — 채워진 파랑
   .is-unanswered (default)         — 빈 외곽선
   .is-flagged   북마크 (별표)      — 우상단 노란 점
   .is-current   지금 보고있는 문항 — 굵은 테두리
*/
.q-nav-item.is-answered {
    background: var(--c-primary);
    color: #fff;
    border-color: var(--c-primary);
}
.q-nav-item.is-flagged::after {
    content: "★";
    position: absolute;
    top: 1px;
    right: 3px;
    font-size: 0.55rem;
    line-height: 1;
    color: var(--c-warning);
    text-shadow: 0 0 2px rgba(0,0,0,0.4);
}
.q-nav-item.is-current {
    outline: 2px solid var(--c-primary);
    outline-offset: 2px;
}

/* 범례 */
.q-nav-legend {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-3);
    margin-top: var(--sp-2);
    font-size: var(--fs-xs);
    color: var(--c-muted);
}
.q-nav-legend > span {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
}
.q-nav-legend i {
    display: inline-block;
    width: 0.85rem;
    height: 0.85rem;
    border-radius: var(--r-sm);
    border: 1px solid var(--c-border);
    background: var(--c-surface);
}
.q-nav-legend i.answered { background: var(--c-primary); border-color: var(--c-primary); }
.q-nav-legend i.flagged  { background: var(--c-surface); position: relative; }
.q-nav-legend i.flagged::after {
    content: "★"; position: absolute; top: -3px; right: -3px;
    font-size: 0.6rem; color: var(--c-warning);
}

/* ============================================================
   11g. 신규 — CBT 응시 도메인 컴포넌트 (Recommended-A §3)
   선지 카드 / 결과 셀 — 색맹 대응 (색 + 모양 이중화)
   ============================================================ */

/* ── 선지 카드 — radio/checkbox 를 큰 클릭 영역의 카드로 ── */
.choice-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: var(--sp-2); }

.choice {
    display: flex;
    align-items: flex-start;
    gap: var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--r-md);
    cursor: pointer;
    transition: border-color var(--t-fast), background var(--t-fast), box-shadow var(--t-fast);
    position: relative;
    line-height: var(--lh-normal);
}
.choice:hover { border-color: var(--c-border-strong); background: var(--c-surface-alt); }
.choice input[type="radio"],
.choice input[type="checkbox"] {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}
.choice-num {
    flex: 0 0 1.75rem;
    height: 1.75rem;
    border-radius: var(--r-pill);
    background: var(--slate-100);
    color: var(--c-fg-soft);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-weight: var(--fw-semi);
    font-size: var(--fs-sm);
    transition: background var(--t-fast), color var(--t-fast);
}
.choice-text { flex: 1; min-width: 0; word-break: keep-all; }
.choice img { max-width: 100%; margin-top: var(--sp-2); border-radius: var(--r-sm); }

/* checked 상태 — radio/checkbox 가 체크되면 부모 .choice 색 변경.
   :has() 셀렉터 사용 (Safari/Chrome/Edge 105+ 지원) */
.choice:has(input:checked) {
    border-color: var(--c-primary);
    background: var(--c-primary-bg);
    box-shadow: 0 0 0 1px var(--c-primary) inset;
}
.choice:has(input:checked) .choice-num {
    background: var(--c-primary);
    color: #fff;
}

/* 응시 후 채점 결과 표시 — .is-correct / .is-wrong / .is-chosen-wrong / .is-missed */
.choice.is-correct {
    border-color: var(--c-success);
    background: var(--c-success-bg);
}
.choice.is-correct .choice-num {
    background: var(--c-success);
    color: #fff;
}
.choice.is-correct::after {
    content: "✓ 정답";
    position: absolute;
    top: var(--sp-2);
    right: var(--sp-3);
    font-size: var(--fs-xs);
    font-weight: var(--fw-semi);
    color: var(--c-success);
    letter-spacing: 0.02em;
}
.choice.is-chosen-wrong {
    border-color: var(--c-danger);
    background: var(--c-danger-bg);
}
.choice.is-chosen-wrong .choice-num {
    background: var(--c-danger);
    color: #fff;
}
.choice.is-chosen-wrong::after {
    content: "✗ 내 답";
    position: absolute;
    top: var(--sp-2);
    right: var(--sp-3);
    font-size: var(--fs-xs);
    font-weight: var(--fw-semi);
    color: var(--c-danger);
}
.choice.is-missed {
    border-color: var(--c-warning);
    background: var(--c-warning-bg);
}
.choice.is-missed::after {
    content: "○ 누락 정답";
    position: absolute;
    top: var(--sp-2);
    right: var(--sp-3);
    font-size: var(--fs-xs);
    color: var(--c-warning);
}
/* 응시 중 disable (제출 후 채점 화면) */
.choice.is-locked {
    cursor: default;
    pointer-events: none;
}

/* ── 결과 셀 (인라인 — 표나 카운트 옆에 작게) ── */
.result-cell {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    padding: 0.15rem 0.5rem;
    border-radius: var(--r-pill);
    font-size: var(--fs-xs);
    font-weight: var(--fw-semi);
    line-height: 1.4;
}
.result-cell-correct { background: var(--c-success-bg); color: var(--c-success); }
.result-cell-correct::before { content: "✓"; font-weight: var(--fw-bold); }
.result-cell-wrong   { background: var(--c-danger-bg);  color: var(--c-danger);  }
.result-cell-wrong::before { content: "✗"; font-weight: var(--fw-bold); }
.result-cell-pending { background: var(--slate-100);    color: var(--c-muted);   }
.result-cell-pending::before { content: "○"; }

/* ============================================================
   11f. 신규 — GOV.UK 영감 패턴 (Recommended-A §2)
   ============================================================ */

/* Skip link — 키보드 사용자가 헤더 건너뛰고 본문 진입 */
.skip-link {
    position: absolute;
    top: -100px;
    left: var(--sp-2);
    z-index: var(--z-toast);
    background: var(--c-fg);
    color: #fff;
    padding: var(--sp-2) var(--sp-3);
    border-radius: var(--r-md);
    text-decoration: none;
    font-weight: var(--fw-semi);
    box-shadow: var(--shadow-md);
    transition: top var(--t-fast);
}
.skip-link:focus,
.skip-link:focus-visible {
    top: var(--sp-2);
    outline: none;
}

/* Error summary — 폼 상단에 모든 검증 오류를 묶어 표시 */
.error-summary {
    border: 4px solid var(--c-danger);
    background: var(--c-surface);
    padding: var(--sp-4) var(--sp-5);
    border-radius: var(--r-md);
    margin-bottom: var(--sp-5);
}
.error-summary[tabindex="-1"]:focus-visible { box-shadow: none; }
.error-summary-title {
    margin: 0 0 var(--sp-2);
    color: var(--c-danger);
    font-size: var(--fs-lg);
    font-weight: var(--fw-semi);
}
.error-summary-list {
    margin: 0;
    padding-left: var(--sp-5);
    color: var(--c-danger);
}
.error-summary-list li { margin-bottom: var(--sp-1); }
.error-summary-list a {
    color: var(--c-danger);
    text-decoration: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 3px;
    font-weight: var(--fw-medium);
}
.error-summary-list a:hover { color: var(--c-danger-hover); }

/* Field-level error — input 옆 빨간 줄 + 메시지 */
.field-with-error {
    border-left: 4px solid var(--c-danger);
    padding-left: var(--sp-3);
    margin-left: calc(var(--sp-3) * -1);
}
.field-error-message {
    color: var(--c-danger);
    font-weight: var(--fw-medium);
    font-size: var(--fs-sm);
    margin: var(--sp-1) 0 0;
}
.field-error-message::before { content: "⚠ "; }

/* Notification banner — 페이지 상단 큰 안내 (Important / Success) */
.notification-banner {
    border: 5px solid var(--c-primary);
    background: var(--c-surface);
    margin-bottom: var(--sp-5);
}
.notification-banner-header {
    background: var(--c-primary);
    color: #fff;
    padding: var(--sp-2) var(--sp-4);
    font-weight: var(--fw-semi);
    font-size: var(--fs-lg);
    letter-spacing: 0.01em;
}
.notification-banner-body {
    padding: var(--sp-4) var(--sp-4);
}
.notification-banner-body .title {
    margin: 0 0 var(--sp-2);
    font-size: var(--fs-lg);
    font-weight: var(--fw-semi);
}
.notification-banner-body p:last-child { margin-bottom: 0; }
/* 변형 */
.notification-banner-success { border-color: var(--c-success); }
.notification-banner-success .notification-banner-header { background: var(--c-success); }
.notification-banner-warning { border-color: var(--c-warning); }
.notification-banner-warning .notification-banner-header { background: var(--c-warning); color: #000; }
.notification-banner-danger { border-color: var(--c-danger); }
.notification-banner-danger .notification-banner-header { background: var(--c-danger); }

/* Inset text — 본문 안에 인용/강조 박스. 좌측 두꺼운 테두리. */
.inset-text {
    padding: var(--sp-3) var(--sp-4);
    border-left: 5px solid var(--c-border-strong);
    background: var(--c-surface);
    margin: var(--sp-4) 0;
}

/* ============================================================
   11i. 신규 — 글로벌 폼 컨트롤 (input / select / textarea / checkbox / radio / file)
   기본 element 셀렉터 → .form-row 와 .field 내부 입력도 같은 톤. 인라인/특수 style 은 우선 적용됨.
   ============================================================ */

input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"],
input[type="tel"],
input[type="url"],
input[type="search"],
input[type="date"],
input[type="datetime-local"],
input[type="time"],
input[type="month"],
input[type="week"],
select,
textarea {
    box-sizing: border-box;
    padding: 0.5rem 0.7rem;
    border: 1px solid var(--c-border);
    border-radius: var(--r-md);
    font: inherit;
    background: var(--c-surface);
    color: var(--c-fg);
    transition: border-color var(--t-fast), box-shadow var(--t-fast), background var(--t-fast);
    min-height: 2.25rem;
    line-height: 1.4;
}

input:focus-visible,
select:focus-visible,
textarea:focus-visible {
    border-color: var(--c-primary);
    box-shadow: var(--focus-ring);
    outline: none;
}

input[disabled],
select[disabled],
textarea[disabled],
input[readonly],
textarea[readonly] {
    background: var(--c-surface-alt);
    color: var(--c-disabled);
    cursor: not-allowed;
    border-color: var(--c-border);
}

input[type="text"]:hover:not(:disabled):not(:focus),
input[type="email"]:hover:not(:disabled):not(:focus),
input[type="password"]:hover:not(:disabled):not(:focus),
input[type="number"]:hover:not(:disabled):not(:focus),
input[type="tel"]:hover:not(:disabled):not(:focus),
input[type="url"]:hover:not(:disabled):not(:focus),
input[type="search"]:hover:not(:disabled):not(:focus),
input[type="date"]:hover:not(:disabled):not(:focus),
input[type="datetime-local"]:hover:not(:disabled):not(:focus),
select:hover:not(:disabled):not(:focus),
textarea:hover:not(:disabled):not(:focus) {
    border-color: var(--c-border-strong);
}

/* select — 커스텀 chevron (네이티브 화살표 숨김) */
select {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.6rem center;
    background-size: 0.85rem;
    padding-right: 2rem;
    cursor: pointer;
}
select:disabled { cursor: not-allowed; }
select[multiple] { background-image: none; padding-right: 0.7rem; min-height: auto; }

/* textarea */
textarea {
    line-height: var(--lh-normal);
    resize: vertical;
    min-height: 5rem;
    height: auto;
}

/* placeholder */
input::placeholder,
textarea::placeholder {
    color: var(--c-disabled);
    opacity: 1;
}

/* file 입력 — 버튼 + 파일명 */
input[type="file"] {
    font: inherit;
    color: var(--c-fg-soft);
    cursor: pointer;
    padding: 0;
    border: 0;
    background: transparent;
}
input[type="file"]::file-selector-button {
    border: 1px solid var(--c-border-strong);
    background: var(--c-surface);
    color: var(--c-fg);
    border-radius: var(--r-md);
    padding: 0.4rem 0.85rem;
    margin-right: 0.6rem;
    cursor: pointer;
    font: inherit;
    font-size: var(--fs-sm);
    transition: background var(--t-fast), border-color var(--t-fast);
}
input[type="file"]::file-selector-button:hover {
    background: var(--c-surface-alt);
    border-color: var(--c-muted);
}

/* checkbox + radio — accent-color 활용 (가벼움), 사이즈 통일 */
input[type="checkbox"],
input[type="radio"] {
    width: 1rem;
    height: 1rem;
    accent-color: var(--c-primary);
    cursor: pointer;
    vertical-align: -0.15em;
    margin: 0;
}
input[type="checkbox"]:disabled,
input[type="radio"]:disabled { cursor: not-allowed; opacity: 0.5; }

/* range slider */
input[type="range"] {
    accent-color: var(--c-primary);
    cursor: pointer;
}

/* color picker — 둥근 모서리 */
input[type="color"] {
    -webkit-appearance: none;
    appearance: none;
    border: 1px solid var(--c-border);
    border-radius: var(--r-md);
    padding: 2px;
    min-height: 2.25rem;
    cursor: pointer;
}

/* search — 기본 cancel 버튼 정리 */
input[type="search"]::-webkit-search-cancel-button { appearance: none; }
input[type="search"]::-webkit-search-decoration { appearance: none; }

/* invalid 상태 — :invalid 또는 .has-error */
input[aria-invalid="true"],
select[aria-invalid="true"],
textarea[aria-invalid="true"] {
    border-color: var(--c-danger);
}
input[aria-invalid="true"]:focus-visible,
select[aria-invalid="true"]:focus-visible,
textarea[aria-invalid="true"]:focus-visible {
    box-shadow: var(--focus-ring-danger);
}

/* fieldset reset */
fieldset {
    border: 1px solid var(--c-border);
    border-radius: var(--r-md);
    padding: var(--sp-3) var(--sp-4);
    margin: 0;
}
legend {
    padding: 0 var(--sp-2);
    font-size: var(--fs-sm);
    font-weight: var(--fw-semi);
    color: var(--c-fg-soft);
}

/* ============================================================
   11j. 신규 — Data Table (사용자·운영자 공용)
   기존 sysop.css 에서 사용자 측에도 적용되도록 승격.
   ============================================================ */

table.data {
    width: 100%;
    /* 컬럼 폭 고정 — th width 값을 그대로 유지, 셀 내용에 따라 흔들리지 않음.
       폭 미지정 컬럼은 잔여 공간을 균등 흡수. 긴 셀 내용은 전역 overflow-wrap 으로 줄바꿈. */
    table-layout: fixed;
    border-collapse: separate;
    border-spacing: 0;
    background: var(--c-surface);
    border: 1px solid var(--c-border);
    border-radius: var(--r-md);
    overflow: hidden;
    margin-bottom: var(--sp-3);
}
table.data th,
table.data td {
    text-align: left;
    padding: 0.55rem 0.75rem;
    border-bottom: 1px solid var(--c-border);
    font-size: var(--fs-sm);
    vertical-align: middle;
}
table.data thead th {
    background: var(--slate-50);
    color: var(--c-muted);
    font-weight: var(--fw-semi);
    font-size: var(--fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-bottom: 1px solid var(--c-border-strong);
}
/* zebra — 가독성 ↑ */
table.data tbody tr:nth-child(even) td { background: var(--slate-50); }
/* row hover — 행 추적 ↑ */
table.data tbody tr { transition: background var(--t-fast); }
table.data tbody tr:hover td { background: var(--c-primary-bg); }
/* 빈 상태 안내 행은 hover 강조 제외 */
table.data tbody tr:hover td.muted[colspan] { background: var(--slate-50); }
table.data tr:last-child td { border-bottom: none; }

/* 문제 본문 미리보기 셀 — 첨부 이미지가 셀 높이를 들쑥날쑥하게 만드는 것 방지. */
table.data td img { display: none; }

table.data .actions { text-align: right; white-space: nowrap; }

/* ─── 액션 컬럼 버튼 위계 통일 ─── */
table.data .actions .btn-link {
    color: var(--c-fg-soft);
    font-size: var(--fs-sm);
    padding: 0.2rem 0.5rem;
}
table.data .actions .btn-link:hover {
    color: var(--c-fg);
    background: var(--slate-100);
    text-decoration: none;
}
table.data .actions .btn-link.js-delete,
table.data .actions .btn-link.danger {
    color: var(--c-danger);
}
table.data .actions .btn-link.js-delete:hover,
table.data .actions .btn-link.danger:hover {
    background: var(--c-danger-bg);
    color: var(--c-danger-hover);
}
table.data .actions .btn-primary {
    font-size: var(--fs-sm);
    padding: 0.25rem 0.65rem;
}

/* ── 레거시 badge 변형 (active/inactive) — 신규 .badge-* 와 별개로 유지 ── */
.badge {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: var(--r-pill);
    font-size: var(--fs-xs);
    font-weight: var(--fw-semi);
}
.badge.active   { background: var(--green-100); color: var(--green-700); }
.badge.inactive { background: var(--slate-200); color: var(--slate-700); }

/* ============================================================
   11. 신규 — Toast (window.toast 가 컨테이너에 동적 삽입)
   ============================================================ */

.toast-container {
    position: fixed;
    bottom: var(--sp-6);
    right: var(--sp-6);
    z-index: var(--z-toast);
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    max-width: 24rem;
    pointer-events: none;
}
.toast {
    pointer-events: auto;
    background: var(--c-surface);
    color: var(--c-fg);
    border: 1px solid var(--c-border);
    border-left: 3px solid var(--c-border-strong);
    border-radius: var(--r-md);
    padding: var(--sp-3) var(--sp-4);
    box-shadow: var(--shadow-lg);
    display: flex;
    align-items: flex-start;
    gap: var(--sp-3);
    font-size: var(--fs-sm);
    animation: toast-in 180ms ease-out;
}
.toast.is-leaving { animation: toast-out 180ms ease-in forwards; }
.toast-success { border-left-color: var(--c-success); }
.toast-error   { border-left-color: var(--c-danger); }
.toast-warning { border-left-color: var(--c-warning); }
.toast-info    { border-left-color: var(--c-info); }
.toast-body  { flex: 1; line-height: var(--lh-normal); }
.toast-close {
    border: 0; background: transparent; cursor: pointer;
    color: var(--c-muted); padding: 0 var(--sp-1);
    font-size: var(--fs-lg); line-height: 1;
}
.toast-close:hover { color: var(--c-fg); }
@keyframes toast-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes toast-out {
    from { opacity: 1; transform: translateY(0); }
    to   { opacity: 0; transform: translateY(8px); }
}

/* ────────── 페이지네이션 (sysop 목록) ────────── */
.pager-nav {
    display: inline-flex;
    align-items: center;
    gap: 2px;
}
.pager-nav .btn-link {
    padding: 0.3rem 0.6rem;
    min-width: 32px;
    text-align: center;
}
.pager-nav .pager-num {
    border: 1px solid var(--c-border);
    border-radius: var(--r-sm);
    background: #fff;
    color: var(--c-fg);
}
.pager-nav .pager-num:hover { background: var(--c-surface-alt); }
.pager-nav .pager-num.is-current {
    background: var(--c-primary);
    border-color: var(--c-primary);
    color: #fff;
    font-weight: var(--fw-semi);
    pointer-events: none;
}
.pager-nav .is-disabled,
.pager-nav .btn-link.is-disabled {
    color: var(--c-muted);
    pointer-events: none;
    opacity: 0.5;
}

/* ============================================================
   스티키 푸터 — 콘텐츠가 짧아도 푸터를 화면 하단에 고정.
   default.html(<body class="app-shell">) 전용. sysop/teacher/take 는
   자체 레이아웃을 쓰므로 영향 없음.
   ============================================================ */
.app-shell {
    display: flex;
    flex-direction: column;
    min-height: 100dvh;
}
.app-shell > main { flex: 1 0 auto; }
.app-shell > .site-footer { flex-shrink: 0; }

/* ============================================================
   12. Ortto Style Layer (DESIGN.md)
   - Snowdrift/Midnight surfaces, Ortto Blue accent, Serif display.
   ============================================================ */

/* 임팩트 헤드라인 — Ivar 톤(Source Serif 4) */
.display-heading,
.ortto-display {
    font-family: var(--ff-display);
    font-weight: 400;
    letter-spacing: -0.01em;
    line-height: 1.05;
    color: var(--c-fg);
}
.display-heading { font-size: clamp(2rem, 4vw + 1rem, var(--fs-headline)); }
.ortto-display   { font-size: clamp(2.5rem, 5vw + 1rem, var(--fs-display)); }

/* 다크 캔버스 섹션 — Midnight Canvas 위 흰 텍스트 */
.surface-midnight {
    background: var(--ortto-midnight);
    color: var(--ortto-snowdrift);
    border-radius: var(--r-section);
}
.surface-midnight .text-muted,
.surface-midnight .muted { color: rgba(255, 255, 255, 0.72); }
.surface-midnight a { color: var(--ortto-snowdrift); }
.surface-midnight .btn-secondary {
    background: transparent;
    color: var(--ortto-snowdrift);
    border-color: rgba(255, 255, 255, 0.4);
}
.surface-midnight .btn-secondary:hover {
    background: rgba(255, 255, 255, 0.08);
    border-color: var(--ortto-snowdrift);
}
.surface-midnight .btn-link { color: var(--ortto-snowdrift); }
.surface-midnight .btn-link:hover { color: var(--ortto-snowdrift); text-decoration: underline; }

/* Aura — 옅은 보조 surface (대비 약하게 분리) */
.surface-aura { background: var(--ortto-aura); border-radius: var(--r-section); }

/* Ortto pill tag — badge 보다 큰 라운드 */
.tag-pill {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    padding: 0.25rem 0.75rem;
    border-radius: var(--r-tag);
    background: var(--ortto-aura);
    color: var(--c-fg-soft);
    border: 1px solid var(--c-border);
    font-size: var(--fs-xs);
    font-weight: var(--fw-medium);
}
.tag-pill.is-accent {
    background: var(--ortto-blue-bg);
    color: var(--ortto-blue);
    border-color: transparent;
}

/* Ortto card — 부드러운 다단 elevation */
.card-feature {
    background: var(--c-surface);
    border-radius: var(--r-section);
    padding: var(--sp-8);
    box-shadow: var(--shadow-card);
    border: none;
}

/* Hero — 다크 패널 좌 + 콘텐츠 우 split */
.hero-split {
    display: grid;
    grid-template-columns: 1.05fr 1fr;
    gap: var(--sp-6);
    align-items: stretch;
    margin-bottom: var(--sp-8);
}
.hero-split > .hero-dark {
    background: var(--ortto-midnight);
    color: var(--ortto-snowdrift);
    border-radius: var(--r-section);
    padding: var(--sp-10) var(--sp-8);
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--sp-5);
}
.hero-split > .hero-light {
    background: var(--ortto-aura);
    border-radius: var(--r-section);
    padding: var(--sp-8);
    display: flex;
    flex-direction: column;
    gap: var(--sp-4);
}
.hero-split .hero-eyebrow {
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-size: var(--fs-xs);
    font-weight: var(--fw-semi);
    color: rgba(255, 255, 255, 0.7);
}
.hero-split .hero-headline {
    /* 한글은 serif(Source Serif) 글리프가 없어 시스템 바탕체로 깨짐 → sans 로 */
    font-family: var(--ff-sans);
    font-weight: 800;
    /* 좁은 hero-dark 패널에서 <br> 기준 2줄 유지되도록 최대 크기 축소 */
    font-size: clamp(1.5rem, 2.4vw + 0.7rem, 2.5rem);
    line-height: 1.3;
    letter-spacing: -0.02em;
    margin: 0;
    color: var(--ortto-snowdrift);
    text-wrap: balance;
}
.hero-split .hero-sub {
    margin: 0;
    font-size: var(--fs-lg);
    line-height: var(--lh-normal);
    color: rgba(255, 255, 255, 0.82);
    max-width: 36rem;
}
.hero-split .hero-actions { display: flex; gap: var(--sp-3); flex-wrap: wrap; }
.hero-split .hero-light .panel-title {
    margin: 0 0 var(--sp-2);
    font-size: var(--fs-xl);
    font-weight: var(--fw-semi);
    color: var(--c-fg);
}
@media (max-width: 860px) {
    .hero-split { grid-template-columns: 1fr; }
    .hero-split > .hero-dark { padding: var(--sp-8) var(--sp-5); }
}

/* Page title — 임팩트 옵션. .page-title.is-display 만 serif 적용 (전역 영향 없음). */
.page-title.is-display {
    font-family: var(--ff-display);
    font-weight: 400;
    font-size: clamp(1.75rem, 2vw + 1rem, 2.5rem);
    letter-spacing: -0.012em;
}

/* Ortto 버튼 컴팩트 변형 — 기본 .btn 이 pill 이므로 sm/lg 도 pill 유지 (overrides 없음).
   .btn-group 내부는 직사각 유지 (기존 정의 이미 처리됨). */
.btn-sm { padding: 0.35rem 1rem; }
.btn-lg { padding: 0.75rem 1.75rem; font-size: var(--fs-lg); }

/* Primary 버튼 — Ortto 액센트 보정 (text contrast 강화) */
.btn-primary { font-weight: var(--fw-semi); }
.btn-primary:focus-visible { box-shadow: 0 0 0 3px rgba(16, 112, 255, 0.35); }
