/* glass.css: 웹 재단장 디자인 시스템. 토큰층 + 컴포넌트층.
   규정 문서: docs/policy/웹-디자인-가이드라인.md
   구 CSS(theme.css, common.css 등)와 독립이다. GC1 동결 화면이 구 CSS를
   참조하므로 이 파일은 새 화면(base.html 상속)에서만 불린다. */

/* ── 토큰층: 테마 무관 공통 ─────────────────────────────────────────── */

:root {
    /* 간격: 8px 배수 체계 */
    --gl-space-1: 8px;
    --gl-space-2: 16px;
    --gl-space-3: 24px;
    --gl-space-4: 32px;
    --gl-space-5: 40px;
    /* 모서리 */
    --gl-radius-s: 9px;
    --gl-radius-m: 14px;
    --gl-radius-l: 22px;
    /* 폭 */
    --gl-content-max: 1080px;
    --gl-sidebar-w: 208px;
    /* 2단 화면(사이드바 + 본문)의 상한. 본문 폭이 1단 화면(gl-main)과 같아지도록
       사이드바 폭, 두 칸 사이 간격, 좌우 padding을 더한 값이다.
       1080 + 208 + 24(gap) + 48(padding 좌우) = 1360 */
    --gl-shell-max: calc(var(--gl-content-max) + var(--gl-sidebar-w) + var(--gl-space-3) * 3);
    /* 글꼴 */
    --gl-font: "IBM Plex Sans KR", "Malgun Gothic", "Segoe UI", sans-serif;
    --gl-fs-body: 15px;
    --gl-fs-small: 13px;
    --gl-fs-h1: 26px;
    --gl-fs-h2: 20px;
    /* 유리 */
    --gl-glass-blur: 18px;
}

/* ── 토큰층: 테마별 값. 네 블록의 토큰 이름 집합은 완전히 같다.
      :root 기본값은 은백(라이트)과 동일: data-theme이 없는 비로그인
      화면이 기본 테마로 렌더된다. ──────────────────────────────────── */

:root,
[data-theme="light"] {
    /* 은백 (라이트, 기본) */
    --gl-bg: linear-gradient(135deg, #e9edf5 0%, #eef1f8 55%, #e7ecf7 100%);
    --gl-glow-a: rgba(76, 98, 216, 0.14);
    --gl-glow-b: rgba(63, 182, 168, 0.10);
    --gl-ink: #1c2438;
    --gl-ink-2: #4a5570;
    --gl-ink-3: #7a84a0;
    --gl-accent: #4c62d8;
    --gl-accent-strong: #3a4fc0;
    --gl-accent-ink: #ffffff;
    --gl-glass-bg: rgba(255, 255, 255, 0.55);
    --gl-glass-bg-2: rgba(255, 255, 255, 0.4);
    --gl-glass-line: rgba(255, 255, 255, 0.8);
    --gl-glass-top: rgba(255, 255, 255, 0.6);
    --gl-shadow: 0 8px 28px rgba(20, 30, 60, 0.12);
    --gl-input-bg: rgba(255, 255, 255, 0.6);
    --gl-input-line: rgba(122, 132, 160, 0.35);
    --gl-hair: rgba(122, 132, 160, 0.22);
    --gl-track: rgba(122, 132, 160, 0.22);
    --gl-info: #2f6db3;
    --gl-info-bg: rgba(59, 130, 246, 0.12);
    --gl-info-line: rgba(59, 130, 246, 0.3);
    --gl-ok: #17703d;
    --gl-ok-bg: rgba(31, 157, 85, 0.14);
    --gl-ok-line: rgba(31, 157, 85, 0.35);
    --gl-warn: #8a5a17;
    --gl-warn-bg: rgba(183, 121, 31, 0.13);
    --gl-warn-line: rgba(183, 121, 31, 0.35);
    --gl-danger: #a02626;
    --gl-danger-bg: rgba(197, 48, 48, 0.10);
    --gl-danger-line: rgba(197, 48, 48, 0.35);
    --gl-scrim: rgba(12, 18, 34, 0.45);
}

[data-theme="dark"] {
    /* 심야 (다크) */
    --gl-bg: linear-gradient(135deg, #14192b 0%, #1a2138 60%, #171e33 100%);
    --gl-glow-a: rgba(143, 160, 255, 0.16);
    --gl-glow-b: rgba(63, 182, 168, 0.08);
    --gl-ink: #eef1fa;
    --gl-ink-2: #aab3cc;
    --gl-ink-3: #7d87a8;
    --gl-accent: #8fa0ff;
    --gl-accent-strong: #a9b6ff;
    --gl-accent-ink: #10142a;
    --gl-glass-bg: rgba(255, 255, 255, 0.07);
    --gl-glass-bg-2: rgba(255, 255, 255, 0.05);
    --gl-glass-line: rgba(255, 255, 255, 0.16);
    --gl-glass-top: rgba(255, 255, 255, 0.12);
    --gl-shadow: 0 8px 28px rgba(0, 0, 0, 0.35);
    --gl-input-bg: rgba(255, 255, 255, 0.08);
    --gl-input-line: rgba(170, 179, 204, 0.3);
    --gl-hair: rgba(170, 179, 204, 0.18);
    --gl-track: rgba(170, 179, 204, 0.2);
    --gl-info: #74c0fc;
    --gl-info-bg: rgba(116, 192, 252, 0.12);
    --gl-info-line: rgba(116, 192, 252, 0.3);
    --gl-ok: #7fdb95;
    --gl-ok-bg: rgba(81, 207, 102, 0.12);
    --gl-ok-line: rgba(81, 207, 102, 0.32);
    --gl-warn: #ffd43b;
    --gl-warn-bg: rgba(255, 212, 59, 0.10);
    --gl-warn-line: rgba(255, 212, 59, 0.3);
    --gl-danger: #ff8787;
    --gl-danger-bg: rgba(255, 135, 135, 0.10);
    --gl-danger-line: rgba(255, 135, 135, 0.32);
    --gl-scrim: rgba(0, 0, 0, 0.58);
}

[data-theme="dawn"] {
    /* 새벽 (웜 라이트) */
    --gl-bg: linear-gradient(135deg, #f7eeea 0%, #f2eaf3 55%, #f5ecec 100%);
    --gl-glow-a: rgba(168, 84, 128, 0.13);
    --gl-glow-b: rgba(216, 150, 86, 0.08);
    --gl-ink: #2e2230;
    --gl-ink-2: #6a5468;
    --gl-ink-3: #97829a;
    --gl-accent: #a85480;
    --gl-accent-strong: #8e4069;
    --gl-accent-ink: #ffffff;
    --gl-glass-bg: rgba(255, 255, 255, 0.55);
    --gl-glass-bg-2: rgba(255, 255, 255, 0.42);
    --gl-glass-line: rgba(255, 255, 255, 0.85);
    --gl-glass-top: rgba(255, 255, 255, 0.65);
    --gl-shadow: 0 8px 28px rgba(90, 50, 70, 0.12);
    --gl-input-bg: rgba(255, 255, 255, 0.62);
    --gl-input-line: rgba(106, 84, 104, 0.32);
    --gl-hair: rgba(106, 84, 104, 0.2);
    --gl-track: rgba(106, 84, 104, 0.2);
    --gl-info: #2f6db3;
    --gl-info-bg: rgba(59, 130, 246, 0.10);
    --gl-info-line: rgba(59, 130, 246, 0.28);
    --gl-ok: #1f7a48;
    --gl-ok-bg: rgba(31, 157, 85, 0.12);
    --gl-ok-line: rgba(31, 157, 85, 0.32);
    --gl-warn: #8a5a17;
    --gl-warn-bg: rgba(183, 121, 31, 0.12);
    --gl-warn-line: rgba(183, 121, 31, 0.32);
    --gl-danger: #a02626;
    --gl-danger-bg: rgba(197, 48, 48, 0.10);
    --gl-danger-line: rgba(197, 48, 48, 0.32);
    --gl-scrim: rgba(12, 18, 34, 0.45);
}

[data-theme="deep"] {
    /* 심해 (딥 틸) */
    --gl-bg: linear-gradient(135deg, #0e2126 0%, #123038 60%, #0f2830 100%);
    --gl-glow-a: rgba(63, 182, 168, 0.16);
    --gl-glow-b: rgba(76, 98, 216, 0.08);
    --gl-ink: #e8f4f2;
    --gl-ink-2: #9dbcb8;
    --gl-ink-3: #6f918d;
    --gl-accent: #3fb6a8;
    --gl-accent-strong: #5ccabd;
    --gl-accent-ink: #0a1f1c;
    --gl-glass-bg: rgba(255, 255, 255, 0.07);
    --gl-glass-bg-2: rgba(255, 255, 255, 0.05);
    --gl-glass-line: rgba(255, 255, 255, 0.16);
    --gl-glass-top: rgba(255, 255, 255, 0.12);
    --gl-shadow: 0 8px 28px rgba(0, 0, 0, 0.35);
    --gl-input-bg: rgba(255, 255, 255, 0.08);
    --gl-input-line: rgba(157, 188, 184, 0.3);
    --gl-hair: rgba(157, 188, 184, 0.18);
    --gl-track: rgba(157, 188, 184, 0.2);
    --gl-info: #74c0fc;
    --gl-info-bg: rgba(116, 192, 252, 0.12);
    --gl-info-line: rgba(116, 192, 252, 0.3);
    --gl-ok: #7fdb95;
    --gl-ok-bg: rgba(81, 207, 102, 0.12);
    --gl-ok-line: rgba(81, 207, 102, 0.32);
    --gl-warn: #ffd43b;
    --gl-warn-bg: rgba(255, 212, 59, 0.10);
    --gl-warn-line: rgba(255, 212, 59, 0.3);
    --gl-danger: #ff8787;
    --gl-danger-bg: rgba(255, 135, 135, 0.10);
    --gl-danger-line: rgba(255, 135, 135, 0.32);
    --gl-scrim: rgba(0, 0, 0, 0.58);
}

/* ── 바탕 ───────────────────────────────────────────────────────────── */

/* UA 기본 [hidden]{display:none}은 display를 지정한 작성자 규칙에 진다.
   gl-btn(inline-flex)이나 gl-stack(flex)에 hidden을 달아도 감춰지게 한다. */
[hidden] { display: none !important; }

.gl-app {
    margin: 0;
    min-height: 100vh;
    background: var(--gl-bg);
    color: var(--gl-ink);
    font-family: var(--gl-font);
    font-size: var(--gl-fs-body);
    line-height: 1.6;
}

.gl-app a { color: var(--gl-accent); text-decoration: none; }
.gl-app a:hover { color: var(--gl-accent-strong); }

h1.gl-h1 { margin: 0; font-size: var(--gl-fs-h1); font-weight: 700; letter-spacing: -0.3px; }
h2.gl-h2 { margin: 0; font-size: var(--gl-fs-h2); font-weight: 700; }

/* ── 유리 표면 (backdrop-filter는 이 셋에만: 상단 바, 카드, 모달) ──── */

.gl-topbar,
.gl-card,
.gl-modal {
    background: var(--gl-glass-bg);
    border: 1px solid var(--gl-glass-line);
    box-shadow: var(--gl-shadow), inset 0 1px 0 var(--gl-glass-top);
    backdrop-filter: blur(var(--gl-glass-blur)) saturate(1.4);
}

/* 굴절층: 기능 감지가 html에 gl-refract를 달았을 때만.
   미지원 브라우저는 이 블록이 적용되지 않아 정제 글래스로 남는다. */
.gl-refract .gl-topbar,
.gl-refract .gl-card,
.gl-refract .gl-modal {
    backdrop-filter: blur(var(--gl-glass-blur)) saturate(1.4) url(#gl-displace);
}

.gl-topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--gl-space-2);
    padding: 12px 22px;
    border-radius: var(--gl-radius-m);
    /* 유리 표면은 저마다 스택 컨텍스트를 만들므로, z-index가 없으면 뒤에
       그려지는 .gl-card가 상단 바의 드롭다운을 덮고 클릭까지 가로챈다.
       상단 바 컨텍스트 전체를 본문 카드 위로 올린다. */
    position: relative;
    z-index: 20;
}

.gl-card {
    border-radius: var(--gl-radius-l);
    padding: var(--gl-space-3);
}

/* 세로로 나열한 카드 사이의 기본 간격. 카드에 바깥 여백이 없고 본문 틀에도 자식
   간격이 없어서, 세로 묶음(.gl-stack)으로 감싸는 것을 아는 사람만 간격을 얻었다.
   2026-09-12 실측으로 카드를 둘 이상 쓰는 화면 열여섯 가운데 감싼 것이 둘뿐이었고
   나머지 열넷은 카드가 맞붙어 보였다. 기본값을 여기 두어 새 화면이 그냥 나열해도
   벌어지게 한다. 자체 간격(gap)을 가진 묶음 안에서는 더해지지 않도록 걷는다. */
.gl-card + .gl-card,
.gl-card + .gl-cards,
.gl-cards + .gl-card { margin-top: var(--gl-space-2); }

.gl-stack > .gl-card + .gl-card,
.gl-cards > .gl-card + .gl-card { margin-top: 0; }

/* 본문 흐름의 공지 상자도 카드와 같은 간격을 둔다(AX-608). 등급 안내 상자가 앞의 메시지 카드와
   뒤의 카드나 표에 맞붙었다(2026-09-16 스테이징 화면 실측). 자체 간격을 가진 묶음 안에서는 걷는다.
   상자 안 자식 사이의 간격은 공지 박스 절의 규칙이다. */
.gl-card + .gl-notice,
.gl-notice + .gl-card,
.gl-notice + .gl-cards,
.gl-notice + .gl-table { margin-top: var(--gl-space-2); }

.gl-stack > .gl-card + .gl-notice,
.gl-stack > .gl-notice + .gl-card,
.gl-shell-body > .gl-card + .gl-notice,
.gl-shell-body > .gl-notice + .gl-card { margin-top: 0; }

.gl-modal {
    border-radius: var(--gl-radius-l);
    padding: var(--gl-space-4);
    max-width: 560px;
}

/* 확인 창 부속: 유리는 .gl-modal 하나뿐이고 나머지는 평면이다.
   폭과 높이는 대응 토큰 갈래가 없는 치수라 직접 쓴다(구 모달에서 옮긴 값). */
.gl-modal-wide { max-width: 780px; width: 100%; max-height: 82vh; overflow-y: auto; }

.gl-overlay {
    position: fixed;
    inset: 0;
    z-index: 1000;              /* 층위: 토큰 갈래 없음 */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--gl-space-3);
    background: var(--gl-scrim);
}

.gl-modal h2 { margin: 0 0 var(--gl-space-1); font-size: var(--gl-fs-h2); font-weight: 700; }

/* 확인 창 안의 공지 상자는 바로 위 표나 합계 줄에 붙는다. 옛 규칙
   .gc2-modal .gc2-notice가 주던 14px를 눈금에 맞춰 대신한다. 새 클래스가 아니라
   기존 컴포넌트의 문맥별 규칙이라 2장 표에 새 줄을 만들지 않는다. */
.gl-modal > .gl-notice { margin-top: var(--gl-space-2); }

.gl-modal-hint { color: var(--gl-ink-3); font-size: var(--gl-fs-small); margin-bottom: var(--gl-space-2); }
.gl-modal-sec { font-weight: 700; margin: var(--gl-space-3) 0 var(--gl-space-1); }
.gl-modal-actions { display: flex; justify-content: flex-end; gap: var(--gl-space-1); margin-top: var(--gl-space-3); }
.gl-modal-total {
    display: flex;
    gap: var(--gl-space-2);
    align-items: baseline;
    margin-top: var(--gl-space-2);
    padding-top: var(--gl-space-2);
    border-top: 1px solid var(--gl-hair);
    font-weight: 700;
}
.gl-modal-total span:last-child { font-weight: 400; color: var(--gl-ink-3); font-size: var(--gl-fs-small); }

/* 표 칸 보조: 정렬과 폭. 폭은 내용에 맞춘 치수라 토큰 갈래가 없다.
   캐스케이드 시험이 짚는 자리라 선택자를 셋으로 맞췄다. 표 밖에서 쓸 수 있게
   맨 클래스도 남긴다. */
.gl-num,
.gl-table th.gl-num,
.gl-table td.gl-num { text-align: right; }
.gl-strong { font-weight: 700; }
.gl-w-lang { width: 150px; }
.gl-w-cost { width: 130px; }
.gl-pick-label { display: flex; gap: var(--gl-space-1); align-items: center; cursor: pointer; }

/* ── 버튼 ───────────────────────────────────────────────────────────── */

.gl-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--gl-space-1);
    font: 600 var(--gl-fs-body) var(--gl-font);
    color: var(--gl-accent-ink);
    background: var(--gl-accent);
    border: 0;
    border-radius: var(--gl-radius-s);
    padding: 10px 20px;
    cursor: pointer;
    transition: background 0.15s ease, transform 0.1s ease;
}
.gl-btn:hover { background: var(--gl-accent-strong); }
.gl-btn:active { transform: translateY(1px); }
.gl-btn:disabled { opacity: 0.45; cursor: not-allowed; transform: none; }
/* 주 단추를 링크로 쓸 때의 짝. `.gl-app a` 가 (0,1,1) 이라 맨 `.gl-btn` (0,1,0) 의 글자색을
   이겨, 강조색 배경 위에 강조색 글자가 놓여 글자가 묻힌다. 보조 단추는 배경이 옅어 묻히지
   않으므로 그동안 드러나지 않았다(2026-09-18 AX-684 스테이징 육안 확인에서 실측).
   hover 짝을 함께 두지 않으면 마우스를 올렸을 때 같은 자리가 다시 어긋난다. */
.gl-app a.gl-btn { color: var(--gl-accent-ink); }
.gl-app a.gl-btn:hover { color: var(--gl-accent-ink); }
.gl-app a.gl-btn-secondary,
.gl-app a.gl-btn-secondary:hover { color: var(--gl-ink-2); }

.gl-btn-secondary {
    color: var(--gl-ink-2);
    background: var(--gl-glass-bg-2);
    border: 1px solid var(--gl-input-line);
}
.gl-btn-secondary:hover { background: var(--gl-input-bg); }

.gl-btn-danger {
    color: #ffffff;
    background: #c53030;
}
.gl-btn-danger:hover { background: #a02626; }

/* ── 입력 계열 ──────────────────────────────────────────────────────── */

.gl-input,
.gl-select {
    font: 400 var(--gl-fs-body) var(--gl-font);
    color: var(--gl-ink);
    background: var(--gl-input-bg);
    border: 1px solid var(--gl-input-line);
    border-radius: var(--gl-radius-s);
    padding: 9px 12px;
    outline: none;
}
.gl-input:focus,
.gl-select:focus {
    border-color: var(--gl-accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--gl-accent) 18%, transparent);
}
.gl-input::placeholder { color: var(--gl-ink-3); }

/* 파일 선택: input[type=file]은 숨기고 label.gl-file을 버튼으로 쓴다 */
.gl-file { cursor: pointer; }
/* 파일 입력을 display:none으로 감추면 접근성 트리와 탭 순서에서 통째로 빠져
   키보드만 쓰는 사람은 파일을 고를 방법이 없다(label은 포커스를 받지 못한다).
   보이지만 않게 하고 자리는 남긴다. 1px과 clip-path는 이 목적의 관용 수치다. */
.gl-file input[type="file"] {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    clip-path: inset(50%);
}
/* 숨긴 입력에 포커스가 가면 감싼 label에 표시한다. 이 파일의 포커스 표시는
   gl-input과 gl-select가 쓰는 3px 반투명 링 하나뿐이라 같은 꼴을 빌린다.
   gl-file은 언제나 gl-btn과 함께 쓰므로 모서리 반경은 그쪽에서 온다. */
.gl-file:focus-within {
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--gl-accent) 18%, transparent);
}

.gl-check {
    appearance: none;
    width: 19px;
    height: 19px;
    border-radius: 6px;
    border: 1.5px solid var(--gl-input-line);
    background: var(--gl-input-bg);
    cursor: pointer;
    display: inline-grid;
    place-content: center;
    transition: background 0.12s ease, border-color 0.12s ease;
}
.gl-check:checked {
    background: var(--gl-accent);
    border-color: var(--gl-accent);
}
.gl-check:checked::before {
    content: "";
    width: 11px;
    height: 9px;
    background: var(--gl-accent-ink);
    clip-path: polygon(10% 55%, 0% 70%, 38% 100%, 100% 18%, 88% 6%, 36% 72%);
}

.gl-label { font-size: 14px; font-weight: 600; color: var(--gl-ink-2); }
.gl-hint { font-size: var(--gl-fs-small); color: var(--gl-ink-3); }

/* ── 진행 게이지 ────────────────────────────────────────────────────── */

.gl-gauge {
    height: 10px;
    border-radius: 5px;
    overflow: hidden;
    background: var(--gl-track);
}
.gl-gauge-fill {
    height: 100%;
    width: 0%;
    border-radius: 5px;
    background: linear-gradient(90deg, var(--gl-accent), color-mix(in srgb, var(--gl-accent) 70%, #ffffff));
    transition: width 0.5s ease;
}
.gl-gauge-fill.gl-gauge-done {
    background: linear-gradient(90deg, #1f9d55, #37b56d);
}

/* ── 상태 배지 (이모지 금지: 낱말 + 4색 토큰) ───────────────────────── */

.gl-badge {
    display: inline-block;
    padding: 2px 11px;
    border-radius: 11px;
    font-size: 12px;
    font-weight: 600;
}
.gl-badge-info { color: var(--gl-info); background: var(--gl-info-bg); border: 1px solid var(--gl-info-line); }
.gl-badge-ok { color: var(--gl-ok); background: var(--gl-ok-bg); border: 1px solid var(--gl-ok-line); }
.gl-badge-warn { color: var(--gl-warn); background: var(--gl-warn-bg); border: 1px solid var(--gl-warn-line); }
.gl-badge-danger { color: var(--gl-danger); background: var(--gl-danger-bg); border: 1px solid var(--gl-danger-line); }

/* 마일스톤 칩: 지나온 단계 ok, 현재 info, 남은 단계 무채색 */
.gl-ms,
.gl-ms-past,
.gl-ms-now {
    display: inline-block;
    padding: 3px 12px;
    border-radius: 11px;
    font-size: 12px;
    font-weight: 600;
    color: var(--gl-ink-3);
    background: color-mix(in srgb, var(--gl-ink-3) 10%, transparent);
    border: 1px solid var(--gl-hair);
}
.gl-ms-past { color: var(--gl-ok); background: var(--gl-ok-bg); border-color: var(--gl-ok-line); }
.gl-ms-now {
    color: var(--gl-accent-strong);
    background: color-mix(in srgb, var(--gl-accent) 14%, transparent);
    border-color: color-mix(in srgb, var(--gl-accent) 35%, transparent);
}

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

.gl-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
}
.gl-table th {
    padding: 7px 10px;
    text-align: left;
    font-weight: 600;
    font-size: var(--gl-fs-small);
    color: var(--gl-ink-3);
    /* 열이 많은 표에서 머리글이 낱말 한가운데서 끊기던 것을 막는다. 브라우저 기본값은
       한국어를 글자 단위로 끊어 "올린 사람" 이 "올린 사" 와 "람" 으로 갈렸다
       (2026-09-18 AX-684 스테이징 육안 확인). 줄바꿈 자체는 그대로 허용하므로 열 폭은
       늘지 않는다 */
    word-break: keep-all;
}
.gl-table td {
    padding: 9px 10px;
    text-align: left;
    border-top: 1px solid var(--gl-hair);
}
.gl-table .gl-row-off { opacity: 0.5; }

/* ── 층 표: 묶음, 언어, 회차 (AX-202) ──────────────────────────────── */
/* 들여쓰기가 곧 깊이다. 색이 아니라 위치로 층을 읽게 한다 */

.gl-table .gl-row-group > td {
    background: color-mix(in srgb, var(--gl-accent) 9%, transparent);
    font-weight: 700;
}
.gl-table .gl-row-chain > td {
    background: color-mix(in srgb, var(--gl-ink-3) 7%, transparent);
}
/* 들여쓰기는 캐럿까지 셈에 넣어야 깊이가 보인다. 언어 줄에는 캐럿이 있고 회차
   줄에는 없으므로(잎이라 접을 것이 없다), 회차 줄에는 캐럿 폭에 한 단을 더 얹는다.
   캐럿 폭만 더하면 두 층의 글자가 같은 x에 서서 계단이 사라진다.
   캐럿 점유 폭과 남는 계단의 실측은 확정 사실 문서 2절. 토큰 갈래가 없는 치수다. */
.gl-row-lang .gl-cell-target { padding-left: var(--gl-space-4); font-weight: 600; }
.gl-row-chain .gl-cell-target {
    /* 언어 줄 + 캐럿 폭 + 한 단 */
    padding-left: calc(var(--gl-space-4) + 26px + var(--gl-space-2));
    font-weight: 500;
}
.gl-total-row td { font-weight: 700; }

.gl-caret {
    display: inline-flex;
    width: 18px;                /* 손잡이 크기: 토큰 갈래 없음 */
    height: 18px;
    align-items: center;
    justify-content: center;
    margin-right: var(--gl-space-1);
    padding: 0;
    border-radius: var(--gl-radius-s);
    border: 1px solid var(--gl-hair);
    background: var(--gl-input-bg);
    color: var(--gl-ink-3);
    cursor: pointer;
    vertical-align: middle;
}
.gl-caret svg { transition: transform 0.15s ease; }
.gl-caret[data-open="1"] svg { transform: rotate(90deg); }

/* 세로 묶음: 카드 안에서 자식 사이를 한 눈금으로 벌린다. 이력 카드는 표 아래에
   안내, 알림, 오류 줄 셋이 붙는데 옛 화면이 각각에 주던 10px, 8px, 8px가 사라진다.
   실행 화면 재단장도 같은 유틸리티를 쓴다(카드 셋, 설정 판, 경보 묶음). */
.gl-stack { display: flex; flex-direction: column; gap: var(--gl-space-2); }

/* 스크립트가 채우는 알림 자리. 비어 있는 동안만 흐름에서 뺀다. 그런 자리는 늘
   렌더되고 대개 비어 있는데 플렉스는 빈 항목에도 gap을 주므로, 그대로 두면 죽은
   여백이 남는다. 실측은 확정 사실 문서 2절에 있다.
   감출 자리를 부모가 아니라 이름으로 지정한다. `:empty`는 "비어 있음"만 보므로
   `.gl-stack > :empty`로 적으면 같은 스택에 든 장식용 빈 요소까지 걷어 간다.
   실행 화면의 `.gl-sep` 구분선이 정확히 그 꼴이라 가로선이 그려지지 않게 된다.
   이름을 단 자리만 감춘다. */
.gl-slot:empty { display: none; }

/* ── 검사 실행 화면 (AX-202) ────────────────────────────────────────── */

.gl-form-row {
    display: flex;
    gap: var(--gl-space-2);
    align-items: center;
    flex-wrap: wrap;
}
/* 입력 라벨은 gl-label이 맡는다. 여기서는 폭만 준다 */
.gl-form-row > .gl-label { min-width: 140px; }   /* 라벨 열 폭: 토큰 갈래 없음 */
.gl-sep { border-top: 1px solid var(--gl-hair); }
.gl-sep-bottom { padding-bottom: var(--gl-space-2); border-bottom: 1px solid var(--gl-hair); }
.gl-grow { flex: 1 1 auto; min-width: 0; }
/* 문장 안 링크. 캐스케이드 시험이 짚는 자리라 접두를 맞췄다. 옛 화면의
   `.gc2-help-link`는 밑줄을 실제로 그렸으므로 그대로 두면 후퇴다. 나머지 세 선언은
   경쟁 상대가 없지만 한 규칙으로 함께 올린다.
   옛 규칙의 다섯 선언 가운데 잇지 않는 하나가 `opacity: 0.85`다. 이 파일에서
   `opacity`가 뜻을 지고 있는 자리는 비활성 상태(`.gl-btn:disabled` 0.45,
   `.gl-row-off` 0.5)라, 살아 있는 링크에 그 값을 얹으면 뜻이 갈린다. 같은 과제
   Step 2b가 넣는 파일 입력의 `opacity: 0`은 뜻이 아니라 시각적 숨김이라 다른
   갈래다. 글자를 낮추어야 하면 색 토큰을 쓰는 것이 이 파일의 관례다. 그만큼 이
   링크가 전보다 또렷해진다. */
.gl-app a.gl-inline-link { margin-left: var(--gl-space-1); font-size: var(--gl-fs-small); text-decoration: underline; white-space: nowrap; }
.gl-w-num { width: 90px; }      /* 숫자 입력 폭: 토큰 갈래 없음 */

/* 공지 상자 자식 사이 간격. 옛 마크업이 자식에 걸던 인라인 8px를 대신한다.
   세로 플렉스로 감싸지 않는 까닭은 안의 버튼이 상자 폭 전체로 늘어나기 때문이다. */
.gl-notice > * + * { margin-top: var(--gl-space-1); }   /* 옛 인라인 8px와 같은 값 */

/* 언어 표 열 폭 고정. auto 배분에 맡기면 배지가 붙었다 사라질 때마다 네 열이
   다시 나뉘어 표가 좌우로 출렁인다. 실측은 docs/superpowers/plans/2026-08-23-web-design-stage2-확정사실.md 3절. */
.gl-table-langs th:nth-child(1) { width: 130px; }   /* 언어 코드 두세 자 */
.gl-table-langs th:nth-child(3) { width: 110px; }   /* 검사 패스 */
.gl-table-langs th:nth-child(4) { width: 200px; }   /* 예상 최대 비용 */

.gl-lang-chip {
    min-width: 52px;            /* 언어 코드 두세 자 기준 */
    text-align: center;
    padding: var(--gl-space-1);
    border-radius: var(--gl-radius-s);
    background: color-mix(in srgb, var(--gl-accent) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--gl-accent) 30%, transparent);
    font-weight: 700;
    font-size: var(--gl-fs-small);
}

.gl-run-row {
    display: flex;
    flex-direction: column;
    gap: var(--gl-space-1);
    padding: var(--gl-space-2) 0;
    border-top: 1px solid var(--gl-hair);
}
.gl-run-row:first-child { border-top: 0; padding-top: 0; }
.gl-run-head { display: flex; align-items: center; gap: var(--gl-space-2); flex-wrap: wrap; }
.gl-chips { display: flex; align-items: center; gap: var(--gl-space-1); flex-wrap: wrap; }
.gl-elapsed { font-size: var(--gl-fs-small); color: var(--gl-ink-3); }

/* 재접속 복원의 묶음 고르기 카드. 유리가 아니라 평면이다(반복 요소) */
.gl-pick {
    cursor: pointer;
    padding: var(--gl-space-2);
    border-radius: var(--gl-radius-s);
    min-width: 280px;           /* 파일 이름이 들어갈 최소 폭 */
    background: var(--gl-input-bg);
    border: 1px solid var(--gl-hair);
}
.gl-pick.active {
    background: color-mix(in srgb, var(--gl-accent) 14%, transparent);
    border-color: color-mix(in srgb, var(--gl-accent) 35%, transparent);
}
.gl-picks { display: flex; gap: var(--gl-space-1); flex-wrap: wrap; }

/* ── 화면 안 이동 두 가지 (AX-607) ──────────────────────────────────────
   이동 링크 줄(gl-links)은 다른 화면으로 가는 링크 묶음이다. 항목 사이에 세로 구분선과 간격을 준다.
   탭 줄(gl-tabs)은 같은 화면에서 여럿 가운데 하나를 고르는 줄이다. 모든 항목이 칩이고 현재 항목만
   aria-current 를 단 span 으로 채운다. 상태 배지(gl-badge)는 상태를 말하는 자리라 탭에 쓰지 않는다.
   링크 칩은 .gl-app a 와 그 hover 에 겹치므로 접두와 상태 짝을 함께 둔다(캐스케이드 시험 subnav). */
.gl-links {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    row-gap: var(--gl-space-1);
    /* 구분선은 항목 바깥 왼쪽의 가상 요소다. 모든 항목이 구분선을 갖고, 줄마다 첫 항목의 구분선이 놓이는
       왼쪽 띠를 잘라 낸다. 앞 항목에만 구분선을 주면 줄이 접힐 때 새 줄 첫 항목이 구분선과 들여쓰기를 달고
       시작한다(검토에서 재현). 잘라 내는 경계는 글자 시작점보다 --gl-space-1 의 절반 앞이라 그 사이에
       링크의 키보드 초점 테두리가 보이고 구분선은 그보다 바깥이라 가려진다(검토에서 초점 왼쪽 변 잘림 재현). */
    margin: var(--gl-space-1) 0 var(--gl-space-1) calc(-2 * var(--gl-space-1) - 1px);
    clip-path: inset(calc(-1 * var(--gl-space-1)) calc(-1 * var(--gl-space-1)) calc(-1 * var(--gl-space-1))
                     calc(1.5 * var(--gl-space-1) + 1px));
    font-size: var(--gl-fs-small);
    line-height: 1.4;
}
.gl-links > * {
    position: relative;
    margin-left: calc(2 * var(--gl-space-1) + 1px);
}
.gl-links > *::before {
    content: "";
    position: absolute;
    left: calc(-1 * var(--gl-space-1) - 1px);
    top: 0.15em;
    bottom: 0.15em;
    width: 1px;
    background: color-mix(in srgb, var(--gl-ink-3) 45%, transparent);
}
.gl-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gl-space-1);
    margin: var(--gl-space-1) 0;
}
.gl-app .gl-tab {
    display: inline-block;
    padding: calc(var(--gl-space-1) / 2) var(--gl-space-2);
    border-radius: var(--gl-radius-l);
    border: 1px solid var(--gl-hair);
    background: var(--gl-input-bg);
    color: var(--gl-ink-2);
    font-size: var(--gl-fs-small);
    font-weight: 500;
    line-height: 1.4;
    white-space: nowrap;
}
.gl-app a.gl-tab { color: var(--gl-ink-2); }
.gl-app a.gl-tab:hover {
    color: var(--gl-accent-strong);
    border-color: color-mix(in srgb, var(--gl-accent) 35%, transparent);
}
.gl-app .gl-tab[aria-current="page"] {
    color: var(--gl-accent-strong);
    background: color-mix(in srgb, var(--gl-accent) 14%, transparent);
    border-color: color-mix(in srgb, var(--gl-accent) 35%, transparent);
    font-weight: 700;
}

/* ── 공지 박스 ──────────────────────────────────────────────────────── */

.gl-notice {
    padding: 12px 16px;
    border-radius: var(--gl-radius-s);
    background: var(--gl-warn-bg);
    border: 1px solid var(--gl-warn-line);
}
.gl-notice-danger {
    background: var(--gl-danger-bg);
    border-color: var(--gl-danger-line);
}
.gl-notice-info {
    background: var(--gl-info-bg);
    border-color: var(--gl-info-line);
}

/* ── 사이드바 ───────────────────────────────────────────────────────── */

.gl-sidebar {
    flex: 0 0 var(--gl-sidebar-w);
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: var(--gl-space-2) 12px;
    border-radius: var(--gl-radius-m);
    background: var(--gl-glass-bg-2);
    border: 1px solid var(--gl-glass-line);
    box-shadow: var(--gl-shadow);
}
.gl-app .gl-sidebar-item {
    display: block;
    padding: 10px 14px;
    border-radius: var(--gl-radius-s);
    font-weight: 500;
    font-size: 14.5px;
    color: var(--gl-ink-2);
    cursor: pointer;
}
.gl-app .gl-sidebar-item:hover { background: var(--gl-input-bg); color: var(--gl-ink-2); }
.gl-app .gl-sidebar-item.active {
    font-weight: 700;
    color: var(--gl-accent-strong);
    background: color-mix(in srgb, var(--gl-accent) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--gl-accent) 35%, transparent);
}
.gl-sidebar-foot {
    border-top: 1px solid var(--gl-hair);
    padding: 12px 14px 4px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.gl-sidebar-foot a {
    font-size: 12px;
    color: var(--gl-ink-3);
    text-decoration: underline;
}

/* ── 앱 셸: 사이드바와 본문 2단 (AX-202) ────────────────────────────── */

/* box-sizing이 필요하다. glass.css에는 이 선언이 하나도 없어 max-width가
   content box에만 걸리고, padding과 border가 그 밖에 따로 붙는다. 그대로 두면
   본문 폭이 1단 화면(gl-main)과 어긋난다.
   .gl-sidebar에 걸리는 이 선언은 과도기 규칙 .top-layer > .gl-sidebar의 렌더 폭도
   좁혀 겹침을 없애는 쪽이라(실측) 손해가 없고, 그 과도기 블록은 마지막 화면
   재단장에서 지워진다. */
.gl-shell,
.gl-sidebar,
.gl-shell-body { box-sizing: border-box; }

.gl-shell {
    position: relative;
    max-width: var(--gl-shell-max);
    margin: 0 auto;
    /* 세로는 gl-main(40px)과 맞춰 상단 바와 첫 카드 사이가 화면마다 같게 한다.
       가로는 사이드바와의 간격 기준이라 24px다. */
    padding: var(--gl-space-5) var(--gl-space-3);
    display: flex;
    gap: var(--gl-space-3);
    align-items: flex-start;
}
.gl-shell-body {
    flex: 1 1 auto;
    min-width: 0;               /* 표가 넘칠 때 사이드바를 밀지 않게 */
    display: flex;
    flex-direction: column;
    gap: var(--gl-space-3);
}
.gl-page-head { display: flex; flex-direction: column; gap: var(--gl-space-1); }
.gl-error { color: var(--gl-danger); white-space: pre-wrap; }
/* 한 카드 안에 같은 꼴의 기록이 여럿 이어질 때 그 사이를 가른다. 붙여 놓으면 어디서
   한 건이 끝나고 다음이 시작하는지 읽히지 않는다(AX-552 스테이징 육안 확인). */
.gl-record + .gl-record {
    margin-top: var(--gl-space-3);
    padding-top: var(--gl-space-3);
    border-top: 1px solid var(--gl-hair);
}
/* 원문 그대로 보이는 기록. 관리자 콘솔의 실패 상세가 러너 원문과 로그 꼬리라 줄이
   길고, 가로로 넘치면 그 칸은 없는 것과 같다(화면 규약: 문장형은 줄을 접는다). */
.gl-pre {
    margin: var(--gl-space-1) 0 0;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    font-size: var(--gl-fs-small);
    color: var(--gl-ink-2);
}

/* 좁은 화면에서는 사이드바를 위로 접는다.
   900px는 `glass.css`(새 디자인 시스템)의 첫 중단점이다. 구 CSS에는 768px와 420px가
   이미 있고, Task 2 Step 9가 그중 768px를 근거로 삼는다.
   사이드바(208) + 본문 최소폭 + 여백 기준. */
@media (max-width: 900px) {
    .gl-shell { flex-direction: column; }
    .gl-sidebar { flex: 0 0 auto; width: 100%; }
    /* 셸에 align-items: flex-start가 걸려 있어 세로로 접힌 뒤에도 본문 칸이
       교차축에서 늘지 않는다. 이 한 줄이 없으면 내용이 좁은 화면에서 사이드바만
       화면 폭을 채우고 그 아래 카드가 절반 남짓으로 남는다. 실측은 확정 사실
       문서 2절에 있다. */
    .gl-shell-body { width: 100%; }
}

/* ── 긴 글 조판: 도움말 (AX-202) ────────────────────────────────────── */

/* max-width는 gl-doc 블록 전체의 내용 폭 상한이다. 노린 것은 긴 산문의 한 줄
   길이이지만 안의 표와 모식도도 함께 묶인다. 옛 .gc2-help가 940px를 걸고 있었고
   그것이 사라지면 도움말 한 줄이 늘어져 읽기 어려워진다. 실측은 확정 사실
   문서 2절에 있다. 토큰 갈래 없음.
   줄간격도 옛 값을 그대로 옮겼다. gl-card-desc의 1.65와 같은 계통이다. */
.gl-doc { max-width: 940px; line-height: 1.75; }
.gl-doc h2 {
    margin: var(--gl-space-4) 0 var(--gl-space-2);
    padding-top: var(--gl-space-2);
    border-top: 1px solid var(--gl-hair);
    font-size: var(--gl-fs-h2);
    font-weight: 700;
}
.gl-doc h3 { margin: var(--gl-space-3) 0 var(--gl-space-1); font-size: var(--gl-fs-body); font-weight: 700; }
.gl-doc p { margin: var(--gl-space-1) 0; }
/* 번호 목록도 같은 들여쓰기를 받는다. ol에 규칙이 없으면 같은 문서 안에서
   글머리 목록과 번호 목록의 항목이 24px 어긋난다(실측). 목차의 ol은
   .gl-doc-index ol이 이겨 영향이 없는데, 이기는 까닭은 특이도가 아니라 문서
   순서다. 둘 다 (0,1,1)로 같고 .gl-doc-index ol이 이 파일에서 뒤에 있다.
   이 규칙을 목차 규칙보다 뒤로 옮기지 말 것. */
.gl-doc ul, .gl-doc ol { margin: var(--gl-space-1) 0 var(--gl-space-1) var(--gl-space-3); }
.gl-doc li { margin: var(--gl-space-1) 0; }
.gl-doc table { width: 100%; border-collapse: collapse; margin: var(--gl-space-2) 0; }
.gl-doc th, .gl-doc td {
    padding: var(--gl-space-1) var(--gl-space-2);
    text-align: left;
    vertical-align: top;
    border-bottom: 1px solid var(--gl-hair);
}
.gl-doc th { white-space: nowrap; color: var(--gl-ink-3); font-size: var(--gl-fs-small); }
/* 화면 문구를 그대로 옮긴 칸: 줄바꿈을 살려 여러 문구를 한 칸에 쌓는다 */
.gl-doc td.gl-doc-msg { white-space: pre-line; font-weight: 600; }
.gl-doc-index {
    margin: 0 0 var(--gl-space-1);
    padding: var(--gl-space-2);
    border-radius: var(--gl-radius-s);
    background: var(--gl-info-bg);
    border: 1px solid var(--gl-info-line);
}
.gl-doc-index ol { margin: var(--gl-space-1) 0 0 var(--gl-space-3); }
/* 화면 모식도: 스크린샷을 두지 않는다. 화면이 바뀌면 그림이 낡고 갱신할 사람이
   없다. 라벨은 messages.py에서 오므로 문구를 고치면 따라 바뀐다. */
.gl-doc-fig-row {
    display: flex;
    gap: var(--gl-space-2);
    align-items: flex-start;
    padding: var(--gl-space-1) var(--gl-space-2);
    margin: var(--gl-space-1) 0;
    border-radius: var(--gl-radius-s);
    border: 1px solid var(--gl-hair);
    background: var(--gl-input-bg);
}
.gl-doc-fig-label { flex: 0 0 34%; font-weight: 700; }   /* 비율: 토큰 갈래 없음 */
.gl-doc-fig-note { flex: 1 1 auto; color: var(--gl-ink-2); }
/* 절 끝 "목차로" 링크. 접두로 .gl-app a:hover와 동률이 되므로 :hover 짝을 함께 둔다. 캐스케이드 시험이 짚는 자리다. */
.gl-app a.gl-doc-top { display: inline-block; margin-top: var(--gl-space-1); font-size: var(--gl-fs-small); color: var(--gl-ink-3); }
.gl-app a.gl-doc-top:hover { color: var(--gl-ink-2); }

/* ── 배경 장식(선택): 은은한 빛망울 두 개. 유리 뒤에 비칠 것 ────────── */

.gl-glow-a,
.gl-glow-b {
    position: fixed;
    border-radius: 50%;
    pointer-events: none;
    z-index: 0;
}
.gl-glow-a {
    top: -180px; right: -120px; width: 560px; height: 560px;
    background: radial-gradient(circle, var(--gl-glow-a) 0%, transparent 70%);
}
.gl-glow-b {
    bottom: -220px; left: -140px; width: 640px; height: 640px;
    background: radial-gradient(circle, var(--gl-glow-b) 0%, transparent 70%);
}

/* ── 공통 셸 (AX-201): 상단 바 내부, 본문 틀, 테마 메뉴 ─────────────── */

.gl-shell-topbar {
    position: relative;
    margin: var(--gl-space-2) var(--gl-space-3) 0;
}

.gl-topbar-brand {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 17px;
    color: var(--gl-accent);
}

.gl-topbar-brand strong { color: var(--gl-ink); letter-spacing: 0.2px; }

.gl-app a.gl-topbar-home {
    display: flex;
    align-items: center;
    gap: 12px;
    /* inherit: SVG 로고는 brand의 강조색을, 포털명 strong은 자체 규칙의
       잉크색을 유지한다 (시안과 동일. ink로 고정하면 로고 색이 죽는다) */
    color: inherit;
}

/* a:hover 기본 규칙과 특이도가 같아 소스 순서로 이긴다. 재배치에 흔들리지
   않도록 명시해 둔다 (브랜드 링크는 hover 색 변화 없음) */
.gl-app a.gl-topbar-home:hover { color: inherit; }

.gl-topbar-path { color: var(--gl-ink-3); font-weight: 500; }

.gl-topbar-right {
    display: flex;
    align-items: center;
    gap: 14px;
}

.gl-topbar-user { color: var(--gl-ink-2); font-size: 14px; font-weight: 500; }
.gl-topbar-logout { margin: 0; }

.gl-main {
    position: relative;
    max-width: var(--gl-content-max);
    margin: 0 auto;
    padding: var(--gl-space-5) var(--gl-space-3);
}

/* 테마 메뉴: details/summary 드롭다운. 유리 표면 제한(상단 바·카드·모달)을
   지키기 위해 목록은 불투명 배경 토큰을 쓴다. */
.gl-menu { position: relative; }

.gl-menu-btn {
    list-style: none;
    cursor: pointer;
    font-size: var(--gl-fs-small);
    font-weight: 500;
    color: var(--gl-ink-2);
    background: var(--gl-input-bg);
    border: 1px solid var(--gl-input-line);
    border-radius: var(--gl-radius-s);
    padding: var(--gl-space-1) var(--gl-space-2);
}

.gl-menu-btn::-webkit-details-marker { display: none; }
.gl-menu-btn::marker { content: none; }
.gl-menu[open] .gl-menu-btn { color: var(--gl-ink); }

.gl-menu-list {
    position: absolute;
    right: 0;
    top: calc(100% + var(--gl-space-1));
    display: flex;
    flex-direction: column;
    gap: calc(var(--gl-space-1) / 4);
    min-width: 120px;           /* 테마 이름 두 글자 넷이 한 줄에 들어갈 최소 폭 */
    padding: calc(var(--gl-space-1) / 2);
    border-radius: var(--gl-radius-s);
    background: var(--gl-input-bg);
    border: 1px solid var(--gl-input-line);
    box-shadow: var(--gl-shadow);
    z-index: 10;
}

.gl-menu-item {
    display: block;
    width: 100%;
    text-align: left;
    font: 500 var(--gl-fs-small) var(--gl-font);
    color: var(--gl-ink-2);
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--gl-radius-s);
    padding: var(--gl-space-1) var(--gl-space-2);
    cursor: pointer;
}

.gl-menu-item:hover { background: var(--gl-track); color: var(--gl-ink); }
/* 현재 테마: 탭 줄의 현재 칩과 같은 표시(화면 안 이동 규정). 색만으로 가르지 않도록 채움과 굵기가 함께 간다 */
.gl-menu-item[aria-current="true"],
.gl-menu-item[aria-current="true"]:hover {
    color: var(--gl-accent-strong);
    background: color-mix(in srgb, var(--gl-accent) 14%, transparent);
    border-color: color-mix(in srgb, var(--gl-accent) 35%, transparent);
    font-weight: 700;
}

/* ── 로그인 화면 (AX-201) ───────────────────────────────────────────── */

.gl-auth {
    position: relative;
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--gl-space-3);
}

.gl-auth-card {
    width: 100%;
    max-width: 420px;
    padding: 44px 42px 38px;  /* 시안 확정값. 8px 배수 예외 */
    display: flex;
    flex-direction: column;
    gap: 20px;                /* 시안 확정값 */
}

.gl-auth-head {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    margin-bottom: 6px;
    color: var(--gl-accent);
}

.gl-auth-head .gl-hint { margin: 0; }
.gl-auth-brand { font-weight: 700; font-size: 21px; color: var(--gl-ink); }

/* 잠금 안내 (AX-570): 로그인 카드 안에 제목과 문단과 돌아가기 링크 */
.gl-auth-title { text-align: center; }
.gl-auth-text { margin: 0; color: var(--gl-ink-2); }
.gl-app a.gl-auth-back { text-align: center; font-weight: 600; }

.gl-field { display: flex; flex-direction: column; gap: 8px; margin-bottom: var(--gl-space-2); }
.gl-field-error { color: var(--gl-danger); font-size: var(--gl-fs-small); }

.gl-pw-row { position: relative; display: flex; align-items: center; }
.gl-pw-row .gl-input { flex: 1; padding-right: 64px; }

.gl-pw-toggle {
    position: absolute;
    right: 10px;
    font: 500 12.5px var(--gl-font);
    color: var(--gl-ink-2);
    background: var(--gl-input-bg);
    border: 1px solid var(--gl-input-line);
    border-radius: 8px;
    padding: 6px 12px;
    cursor: pointer;
}

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

/* ── 런처 대시보드 (AX-201) ─────────────────────────────────────────── */

.gl-eyebrow {
    font-size: var(--gl-fs-body);
    font-weight: 500;
    color: var(--gl-ink-3);
    margin-bottom: 6px;
}

.gl-launcher-title { margin-bottom: var(--gl-space-4); }

.gl-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 28px;
}

.gl-app a.gl-card-link {
    display: block;
    color: var(--gl-ink);
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.gl-app a.gl-card-link:hover {
    color: var(--gl-ink);
    transform: translateY(-4px);
}

.gl-card-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    border-radius: 15px;
    background: var(--gl-info-bg);
    color: var(--gl-accent);
    margin-bottom: 20px;
}

.gl-card-icon-alt { background: var(--gl-ok-bg); color: var(--gl-ok); }

.gl-card-title { font-size: var(--gl-fs-h2); font-weight: 700; margin-bottom: 8px; }
.gl-card-desc { font-size: 14.5px; line-height: 1.65; color: var(--gl-ink-2); }

.gl-foot-link {
    position: fixed;
    bottom: 22px;
    right: 40px;
    font-size: var(--gl-fs-small);
}

.gl-app .gl-foot-link a { color: var(--gl-ink-3); text-decoration: underline; }

/* ── 접근성: 움직임 줄이기 설정 존중. 파일 맨 끝에 둔다(아래 까닭) ──── */

@media (prefers-reduced-motion: reduce) {
    .gl-app a.gl-card-link,
    .gl-btn,
    .gl-caret svg,
    .gl-check,
    .gl-gauge-fill,
    .gl-input,
    .gl-select {
        transition: none;
    }
}
