/*
 * ASTA 프론트엔드 A (Twig) 스타일시트.
 *
 * 색·타입·간격·모서리 값은 **여기서 정의하지 않는다** — `tokens.css` 가 유일한
 * 원본이고 Vue 쪽도 같은 파일을 쓴다(`npm run build:tokens`). 스케일에 없는 값이
 * 필요하면 토큰을 늘리고 두 프론트에 함께 적용한다.
 *
 * 파일 순서 = 캐스케이드 순서다. 아래로 갈수록 좁은 범위를 다룬다.
 *
 *   1. 기반          — 토큰 브리지, body, 링크
 *   2. 셸            — 사이드바 · 상단바 · 본문 · 반응형
 *   3. 페이지 헤더
 *   4. 카드 · 섹션
 *   5. 폼 · 필터
 *   6. 버튼 · 터치 타깃
 *   7. 배지 · 상태
 *   8. 표
 *   9. 화면별
 *  10. 한/영 전환
 *
 * 한 컴포넌트의 규칙은 한 곳에 모은다. 전에는 상태 배지 색이 두 군데, 사이드바
 * 브랜드가 두 군데에 있었고 파일 끝이 특이도 싸움 구역이었다 — 고칠 때 어느 쪽을
 * 고쳐야 하는지 알 수 없었다.
 */
@import url("tokens-g_fdfJq.css");
@import url("vendor/bootstrap-icons/bootstrap-icons.min-5BD67CJ.css");

/* ══ 1. 기반 ═══════════════════════════════════════════════════════ */

/*
 * Bootstrap 을 같은 토큰에 묶는다. 두 색·타입 체계가 갈리면 다크 모드에서 대비가
 * 깨지고 글자 크기가 화면마다 달라진다. Bootstrap 5.3 은 대부분을 CSS 변수로
 * 노출하므로 여기서 한 번에 맞출 수 있다.
 */
:root {
    --bs-body-bg: var(--page-bg);
    --bs-body-color: var(--text);
    --bs-body-font-family: var(--font-sans);
    --bs-body-font-size: var(--text-base);
    --bs-body-line-height: var(--leading-normal);
    --bs-border-color: var(--border);
    --bs-border-radius: var(--radius);
    --bs-border-radius-sm: var(--radius-sm);
    --bs-border-radius-lg: var(--radius-lg);
    --bs-secondary-color: var(--text-muted);
    --bs-secondary-bg: var(--surface-3);
    --bs-tertiary-bg: var(--surface-2);
    --bs-emphasis-color: var(--text);
    --bs-link-color: var(--accent-text);
    --bs-link-hover-color: var(--accent-text);
    --bs-font-monospace: var(--font-mono);
    /*
     * Bootstrap 의 `code` 기본색은 분홍(`#d63384`)이다. 흰 배경에서 4.1:1 로 대비가
     * 모자라 axe 의 color-contrast 에 걸린다 — 현장 코드·감사 액션이 전부 `<code>` 라
     * 표에서 여러 줄이 한꺼번에 걸렸다. 글자용 토큰으로 바꾼다 (docs/14 §3).
     */
    --bs-code-color: var(--text);
}

/*
 * `<code>` 는 값이 아니라 **식별자**다(현장 코드, 감사 액션, CSV 열 이름). 옅은 배경으로
 * 주변 글과 구분하되 색으로 강조하지는 않는다.
 */
code {
    padding: 0 var(--space-1);
    border-radius: var(--radius-sm);
    background-color: var(--surface-3);
    font-size: var(--text-sm);
}

/* `<pre>` 안에서는 배경·여백을 다시 주지 않는다. 컨테이너가 이미 갖고 있다. */
pre code {
    padding: 0;
    background-color: transparent;
    font-size: inherit;
}

body {
    background-color: var(--page-bg);
    color: var(--text);
    font-family: var(--font-sans);
}

/*
 * 링크 색. Bootstrap 은 `--bs-link-color` 가 아니라 `--bs-link-color-rgb`(RGB 삼중항)를
 * 쓰기 때문에 변수 브리지만으로는 닿지 않는다. 토큰을 그대로 쓰려면 규칙으로 쓴다 —
 * Vue 쪽도 같다.
 */
a {
    color: var(--accent-text);
}

/* 포커스 링은 두 프론트에서 같아야 한다 — 키보드 사용자가 배우는 신호다. */
:focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
}

.app-surface-2 {
    background-color: var(--surface-2);
}

/* ══ 2. 셸 ════════════════════════════════════════════════════════
   상단 바가 아니라 사이드바다. 항목이 15개를 넘어가는데 가로로 늘어놓으면 좁은
   화면에서 접혀 버리고, 매일 쓰는 항목을 찾는 데 시간이 든다.

   크롬(사이드바·상단바)과 카드는 같은 `--card-bg` 를 쓰고, 본문 평면만
   `--page-bg` 로 한 단 눌린다. 그래서 카드가 어디서든 같은 높이로 떠오른다. */

.app-shell {
    display: flex;
    min-height: 100vh;
}

.app-sidebar {
    display: flex;
    flex-direction: column;
    flex: 0 0 var(--sidebar-width);
    width: var(--sidebar-width);
    background-color: var(--card-bg);
    border-right: 1px solid var(--border);
    /* 본문이 길어도 메뉴는 항상 보인다. */
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
    transition: flex-basis .15s ease, width .15s ease;
}

/* 레일 모드 — 아이콘만 남긴다. */
.app-shell.is-collapsed .app-sidebar {
    flex-basis: var(--sidebar-rail);
    width: var(--sidebar-rail);
}

.app-shell.is-collapsed .sidebar__label,
.app-shell.is-collapsed .sidebar__chevron {
    display: none;
}

.app-shell.is-collapsed .sidebar__link,
.app-shell.is-collapsed .sidebar__group-toggle,
.app-shell.is-collapsed .sidebar__brand,
.app-shell.is-collapsed .sidebar__user {
    justify-content: center;
}

.app-shell.is-collapsed .sidebar__collapse i {
    transform: rotate(180deg);
}

/* 레일에서는 관리자 하위 항목을 들여쓰지 않는다 — 아이콘이 어긋나 보인다. */
.app-shell.is-collapsed .sidebar__sublist .sidebar__link {
    padding-left: var(--space-2);
}

.sidebar__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    padding: var(--space-3);
    border-bottom: 1px solid var(--border);
}

/* 브랜드도 대시보드로 가는 링크다. 24px 면 누르기 어렵다. */
.sidebar__brand {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
    min-height: var(--touch-target);
    color: var(--text);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
}

.sidebar__nav {
    flex: 1 1 auto;
    padding: var(--space-2) 0;
}

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

.sidebar__link {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    /* 터치 타깃 44px (docs/06 §9). 패딩만으로는 39px 에 그쳤다. */
    min-height: var(--touch-target);
    padding: var(--space-2);
    margin-bottom: var(--space-0);
    border-radius: var(--radius);
    color: var(--text);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    /*
     * 넘치면 말줄임표를 보인다. 그냥 자르면 "Exenciones de descans" 처럼 **다른 낱말로
     * 읽혀서** 잘린 줄 모른다. 스페인어 라벨은 영어보다 15~25% 길다. 전체 문구는
     * `title`(툴팁)에 있다.
     */
    text-overflow: ellipsis;
}

.sidebar__link i {
    flex: 0 0 1.25rem;
    text-align: center;
}

.sidebar__link:hover {
    background-color: var(--surface-3);
    color: var(--accent-text);
    text-decoration: none;
}

/* 현재 위치. 왼쪽 막대가 있어야 레일 모드에서도 어디 있는지 보인다. */
.sidebar__link.is-active {
    background-color: var(--accent-tint);
    color: var(--accent-text);
    font-weight: 600;
    box-shadow: inset 3px 0 0 var(--accent);
}

/* 관리자 그룹 — 설정·감사처럼 가끔 쓰는 것을 따로 묶는다. */
.sidebar__group {
    margin-top: var(--space-2);
    padding-top: var(--space-2);
    border-top: 1px solid var(--border);
}

.sidebar__group-toggle {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    width: calc(100% - var(--space-4));
    min-height: var(--touch-target);
    margin: 0 var(--space-2) var(--space-0);
    padding: var(--space-2);
    border: 0;
    border-radius: var(--radius);
    background-color: transparent;
    color: var(--text-muted);
    font-size: var(--text-sm);
    font-weight: 600;
    letter-spacing: .02em;
    text-transform: uppercase;
    white-space: nowrap;
}

.sidebar__group-toggle:hover {
    background-color: var(--surface-3);
    color: var(--text);
}

.sidebar__group-toggle i:first-child {
    flex: 0 0 1.25rem;
    text-align: center;
}

.sidebar__chevron {
    margin-left: auto;
    transition: transform .15s ease;
}

.sidebar__group-toggle[aria-expanded="false"] .sidebar__chevron {
    transform: rotate(-90deg);
}

.sidebar__sublist .sidebar__link {
    padding-left: var(--space-5);
    font-size: var(--text-base);
}

.sidebar__foot {
    padding: var(--space-3);
    border-top: 1px solid var(--border);
}

.sidebar__user {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
    margin-bottom: var(--space-2);
    color: var(--text-muted);
    font-size: var(--text-sm);
    white-space: nowrap;
    overflow: hidden;
}

.sidebar__actions {
    display: flex;
    gap: var(--space-1);
}

.app-main {
    flex: 1 1 auto;
    min-width: 0;   /* 넓은 표가 셸을 밀지 않게 한다 */
    display: flex;
    flex-direction: column;
}

.app-content {
    flex: 1 1 auto;
    padding: var(--space-4) var(--space-5) var(--space-7);
}

.app-content--bare {
    max-width: 32rem;
    margin: 0 auto;
}

/* 좁은 화면 전용 상단 바. 넓은 화면에서는 사이드바가 그 역할을 한다. */
.app-topbar {
    display: none;
    align-items: center;
    gap: var(--space-3);
    min-height: var(--topbar-height);
    padding: var(--space-2) var(--space-3);
    background-color: var(--card-bg);
    border-bottom: 1px solid var(--border);
}

.app-topbar__brand {
    color: var(--text);
    font-weight: 600;
    text-decoration: none;
}

.app-scrim {
    display: none;
}

/* 브레이크포인트는 1024 / 1440 만 쓴다 (CLAUDE.md 프론트 규약). */
@media (max-width: 1023.98px) {
    .app-topbar {
        display: flex;
    }

    /* 오프캔버스 — 자리를 차지하지 않고 위로 덮는다. */
    .app-sidebar {
        position: fixed;
        z-index: 1045;
        top: 0;
        bottom: 0;
        left: 0;
        height: 100%;
        transform: translateX(-100%);
        transition: transform .15s ease;
    }

    .app-shell.is-open .app-sidebar {
        transform: translateX(0);
    }

    /* 좁은 화면에서는 레일 모드를 쓰지 않는다 — 아이콘만 남기면 덮개가 무의미하다. */
    .app-shell.is-collapsed .app-sidebar {
        flex-basis: var(--sidebar-width);
        width: var(--sidebar-width);
    }

    .app-shell.is-collapsed .sidebar__label,
    .app-shell.is-collapsed .sidebar__chevron {
        display: inline;
    }

    .app-shell.is-open .app-scrim {
        display: block;
        position: fixed;
        z-index: 1040;
        inset: 0;
        background-color: var(--scrim);
    }
}

@media (min-width: 1440px) {
    .app-content {
        padding: var(--space-5) var(--space-6) var(--space-7);
    }
}

/* ══ 3. 페이지 헤더 (partials/_page_header.html.twig 전용) ══════════ */

.page-header {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
    align-items: flex-start;   /* 모바일에서 열이 부풀어 잘리지 않게 한다 */
    justify-content: space-between;
    padding: var(--space-4) 0;
    border-bottom: 1px solid var(--border);
}

.page-header__title {
    display: flex;
    gap: var(--space-3);
    align-items: flex-start;
    margin: 0;
    font-size: var(--text-lg);
    font-weight: 600;
}

.page-header__subtitle {
    margin: var(--space-1) 0 0;
    color: var(--text-muted);
    font-size: var(--text-sm);
}

.page-header__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

/* ══ 4. 카드 · 섹션 ═══════════════════════════════════════════════
   본문 평면(`--page-bg`)보다 밝게 떠오른다. 테두리와 얕은 그림자를 함께 쓴다 —
   짙은 그림자를 얹으면 테두리와 겹쳐 탁해진다. */

.app-card {
    padding: var(--space-4);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background-color: var(--card-bg);
    box-shadow: var(--shadow-sm);
}

/*
 * 관리자 폼의 폭. 표·리포트는 넓을수록 좋지만 폼은 아니다 — 입력칸이 통째로
 * 늘어나면 라벨과 값 사이가 멀어져 어느 라벨의 칸인지 놓친다 (docs/14 §2).
 */
.admin-form {
    max-width: var(--form-max);
}

/*
 * 읽기 전용 항목 목록(항목명 / 값). Vue 쪽 `.meta` 와 같은 모양이다.
 * 입력칸 사이에 끼워 두면 고칠 수 있는 값으로 읽히므로 따로 낸다.
 */
.meta-list {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--space-1) var(--space-4);
    margin: 0;
    font-size: var(--text-sm);
}

.meta-list dt {
    font-weight: 400;
    color: var(--text-muted);
}

.meta-list dd {
    margin: 0;
}

.section-title {
    padding-bottom: var(--space-2);
    margin-bottom: var(--space-4);
    border-bottom: 1px solid var(--border);
    font-size: var(--text-md);
    font-weight: 600;
}

/* ══ 5. 폼 · 필터 ═════════════════════════════════════════════════
   폼 테마는 `bootstrap_5_layout.html.twig` 로 고정한다 (config/packages/twig.yaml).
   비워 두면 `form_row()` 필드에 `form-control` 이 붙지 않아 입력칸이 브라우저
   기본 폭(약 170px)에 묶이고 라벨이 인라인으로 붙는다 — CSS 로는 못 고친다. */

.filter-form .form-label {
    margin-bottom: var(--space-1);
    font-size: var(--text-sm);
    font-weight: 600;
}

/* 도움말은 라벨보다 약하게. Bootstrap 기본값은 본문과 같은 크기다. */
.form-text {
    font-size: var(--text-xs);
    color: var(--text-muted);
}

/* ══ 6. 버튼 · 터치 타깃 ══════════════════════════════════════════
   현장에서 장갑 낀 손으로 누르는 화면이다. Bootstrap 의 `.btn` 기본 높이는 38px 라
   규칙(44px)에 못 미치므로 여기서 한 번에 올린다 — 화면마다 `py-*` 를 붙이면
   빠뜨린 곳이 생기고, 빠뜨렸는지는 눌러 봐야 알 수 있다.

   예외는 **선택자 특이도가 아니라 토큰 재정의**로 만든다. 전에는 `.btn:not(.btn-sm)`
   과 `.btn.time-clock__button` 이 특이도를 다투다 큰 버튼이 44px 로 덮였다.
   지역에서 `--touch-target` 만 바꾸면 싸울 일이 없다. */

.btn,
.nav-tabs .nav-link,
.form-control,
.form-select {
    min-height: var(--touch-target);
}

/* 아이콘만 있는 버튼·링크는 **너비도** 타깃이다. 초기화(x) 링크가 42px 로 남아 있었다. */
.btn {
    min-width: var(--touch-target);
}

/* 표 안의 행 단위 버튼. 44px 로 키우면 표가 읽히지 않는다. */
.btn-sm {
    --touch-target: var(--touch-target-dense);
}

/*
 * 페이저는 촘촘한 것이 목적이다 — 44px 로 키우면 일곱 칸이 화면을 가로지른다. 다만
 * Bootstrap 기본값은 24×31 로 너무 작았다. 촘촘한 타깃 토큰(32px)에 맞춰 Vue 쪽
 * `.pager .btn` 과 같은 크기로 둔다.
 */
.page-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--touch-target-dense);
    min-height: var(--touch-target-dense);
}

/* 출근·퇴근은 그 화면의 유일한 큰 버튼이다 (docs/06 §9). */
.time-clock__button {
    --touch-target: var(--touch-target-primary);
}

/*
 * 아웃라인 버튼을 토큰에 묶는다.
 *
 * Bootstrap 5.3 의 `[data-bs-theme="dark"]` 는 아웃라인 버튼의 색을 다시 잡아 주지
 * **않는다** — `.btn-outline-secondary` 는 어느 테마에서나 회색 `#6c757d` 를 쓰고,
 * 어두운 카드(#2d2d2d) 위에서 대비가 2.94:1 까지 떨어졌다. 21곳에서 쓰는 가장 흔한
 * 보조 버튼이라 여기서 한 번에 고친다.
 *
 * 값은 Vue 쪽 `.btn` / `.btn-danger` 와 같게 맞춘다 — 같은 자리의 버튼이 두 프론트에서
 * 다르게 보이지 않게.
 */
.btn-outline-secondary {
    --bs-btn-color: var(--text);
    --bs-btn-border-color: var(--border);
    --bs-btn-bg: var(--card-bg);
    --bs-btn-hover-color: var(--text);
    --bs-btn-hover-bg: var(--surface-3);
    --bs-btn-hover-border-color: var(--border);
    --bs-btn-active-color: var(--text);
    --bs-btn-active-bg: var(--surface-3);
    --bs-btn-active-border-color: var(--border);
    --bs-btn-disabled-color: var(--text-muted);
    --bs-btn-disabled-border-color: var(--border);
}

.btn-outline-primary {
    --bs-btn-color: var(--accent-text);
    --bs-btn-border-color: var(--accent);
    --bs-btn-hover-color: var(--accent-contrast);
    --bs-btn-hover-bg: var(--accent);
    --bs-btn-hover-border-color: var(--accent);
    --bs-btn-active-color: var(--accent-contrast);
    --bs-btn-active-bg: var(--accent);
    --bs-btn-active-border-color: var(--accent);
    --bs-btn-disabled-color: var(--text-muted);
    --bs-btn-disabled-border-color: var(--border);
}

.btn-outline-danger {
    --bs-btn-color: var(--danger-text);
    --bs-btn-border-color: var(--danger-line);
    --bs-btn-hover-color: var(--accent-contrast);
    --bs-btn-hover-bg: var(--danger);
    --bs-btn-hover-border-color: var(--danger);
    --bs-btn-active-color: var(--accent-contrast);
    --bs-btn-active-bg: var(--danger);
    --bs-btn-active-border-color: var(--danger);
    --bs-btn-disabled-color: var(--text-muted);
    --bs-btn-disabled-border-color: var(--border);
}

.btn-outline-success {
    --bs-btn-color: var(--success-text);
    --bs-btn-border-color: var(--success-line);
    --bs-btn-hover-color: var(--accent-contrast);
    --bs-btn-hover-bg: var(--success);
    --bs-btn-hover-border-color: var(--success);
    --bs-btn-active-color: var(--accent-contrast);
    --bs-btn-active-bg: var(--success);
    --bs-btn-active-border-color: var(--success);
    --bs-btn-disabled-color: var(--text-muted);
    --bs-btn-disabled-border-color: var(--border);
}

/*
 * 셸의 토글 버튼(사이드바 접기 · 좁은 화면 메뉴). 아이콘만 있는 버튼이라
 * **크기가 곧 타깃**이다 (docs/06 §9).
 */
.sidebar__collapse,
.app-topbar__menu {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--touch-target);
    height: var(--touch-target);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background-color: transparent;
    color: var(--text-muted);
}

.sidebar__collapse:hover,
.app-topbar__menu:hover {
    border-color: var(--accent);
    color: var(--accent-text);
}

/*
 * 아이콘 버튼 — **원형 아이콘 + 툴팁**이다.
 * 전에는 hover 하면 라벨이 옆으로 펼쳐졌는데, 그때 폭이 변해 옆 버튼들이 밀렸다.
 * 이름은 툴팁(`tooltip_controller.js`)이 띄우고, 화면 낭독기는 감춘 라벨을 읽는다.
 */
.icon-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* 정사각형이어야 원이 된다. min-* 만 주면 내용에 따라 타원이 된다. */
    flex: 0 0 auto;
    width: var(--touch-target);
    height: var(--touch-target);
    padding: 0;
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    background-color: var(--card-bg);
    color: var(--text);
    font-size: var(--text-md);
    line-height: 1;
    text-decoration: none;
}

.icon-pill:hover,
.icon-pill:focus-visible {
    border-color: var(--accent);
    color: var(--accent-text);
}

.icon-pill--primary {
    border-color: var(--accent);
    background-color: var(--accent);
    color: var(--accent-contrast);
}

.icon-pill--primary:hover,
.icon-pill--primary:focus-visible {
    color: var(--accent-contrast);
    filter: brightness(1.08);
}

/*
 * 라벨은 DOM 에 남긴다 — 이것이 버튼의 접근 가능한 이름이다. `aria-label` 로 대체하면
 * 툴팁 문구와 낭독 문구가 갈라진다.
 */
.icon-pill__label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ══ 7. 배지 · 상태 ═══════════════════════════════════════════════
   옅은 틴트 채움 + 테두리 + 글자용 색. 세 값을 토큰 한 쌍에서 가져오므로 Vue 쪽
   배지와 같은 모양이 된다 — 전에는 Twig 이 테두리만, Vue 가 틴트 채움이라 같은
   상태가 다르게 보였다.

   상태 키와 클래스는 1:1 로 둔다 (CLAUDE.md 12). */

.status-badge {
    display: inline-block;
    padding: var(--space-0) var(--space-2);
    border: 1px solid var(--neutral-line);
    border-radius: var(--radius-pill);
    background-color: var(--neutral-tint);
    /* 심각도 클래스가 없어도 읽혀야 한다. Bootstrap 의 `.badge` 는 흰 글자가
       기본이라 배경 없는 배지에서 글자가 사라진다. */
    color: var(--text);
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
    white-space: nowrap;
}

/* TimeEntryStatus::severity() 와 1:1 */
.status-badge--normal {
    border-color: var(--success-line);
    background-color: var(--success-tint);
    color: var(--success-text);
}

.status-badge--warn {
    border-color: var(--warning-line);
    background-color: var(--warning-tint);
    color: var(--warning-text);
}

.status-badge--danger {
    border-color: var(--danger-line);
    background-color: var(--danger-tint);
    color: var(--danger-text);
}

.status-badge--info {
    border-color: var(--accent-line);
    background-color: var(--accent-tint);
    color: var(--accent-text);
}

/* EmployeeStatus 와 1:1 */
.status-badge--active {
    border-color: var(--success-line);
    background-color: var(--success-tint);
    color: var(--success-text);
}

.status-badge--inactive {
    border-color: var(--neutral-line);
    background-color: var(--neutral-tint);
    color: var(--text-muted);
}

.status-badge--terminated {
    border-color: var(--danger-line);
    background-color: var(--danger-tint);
    color: var(--danger-text);
}

/*
 * 개수 배지 (탭 건수 · 그룹 건수).
 *
 * 상태 배지와 **모양을 나눈다** — 테두리 없는 채움이다. 같은 화면에서 둘이 같아
 * 보이면 "지각 3" 이 상태인지 건수인지 알 수 없다. 전에는 Bootstrap 의
 * `.badge.text-bg-secondary` 를 섞어 써서 한 화면에 배지 체계가 두 개였다.
 */
.count-badge {
    display: inline-block;
    min-width: 1.5rem;
    padding: 0 var(--space-1);
    border-radius: var(--radius-pill);
    background-color: var(--neutral-tint);
    color: var(--text);
    font-size: var(--text-xs);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    text-align: center;
}

.count-badge--info {
    background-color: var(--accent-tint);
    color: var(--accent-text);
}

.count-badge--warn {
    background-color: var(--warning-tint);
    color: var(--warning-text);
}

.count-badge--danger {
    background-color: var(--danger-tint);
    color: var(--danger-text);
}

/* 팀 현황 — 지금 일하는 중인지 아닌지가 한눈에 보여야 해서 채움을 진하게 쓴다. */
.presence {
    border: 1px solid transparent;
}

.presence--working {
    background-color: var(--success);
    border-color: var(--success);
    color: var(--accent-contrast);
}

.presence--finished {
    background-color: var(--neutral-tint);
    border-color: var(--neutral-line);
    color: var(--text-muted);
}

.presence--absent {
    background-color: var(--danger-tint);
    border-color: var(--danger-line);
    color: var(--danger-text);
}

/* ══ 8. 표 ════════════════════════════════════════════════════════
   숫자 열이 많아 눈이 미끄러진다. 폭이 넓은 화면에서는 카드가 아니라 **표**로 낸다
   (CLAUDE.md 프론트 규약). */

.report-table {
    font-variant-numeric: tabular-nums;
}

.report-table thead th {
    white-space: nowrap;
    font-size: var(--text-sm);
    color: var(--text-muted);
}

.report-table tbody td {
    white-space: nowrap;
}

/* 합계 행은 눈에 띄어야 한다 — 여기가 급여로 넘어가는 숫자다. */
.report-table__totals > * {
    background-color: var(--surface-3);
    font-weight: 600;
}

.report-table .badge + .badge {
    margin-left: var(--space-1);
}

.inbox-table td {
    vertical-align: middle;
}

.comparison-table th[scope="row"] {
    font-weight: 400;
    color: var(--text-muted);
}

.comparison-table td {
    font-variant-numeric: tabular-nums;
}

/* 감사로그의 before/after JSON. 넓은 값이 표를 밀지 않게 자기 안에서 스크롤한다. */
.audit-json {
    margin: 0;
    padding: var(--space-1) var(--space-2);
    background-color: var(--surface-2);
    border-radius: var(--radius-sm);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    max-height: 14rem;
    overflow: auto;
    white-space: pre;
}

/* ══ 9. 화면별 ════════════════════════════════════════════════════ */

/* ── 로그인 ─────────────────────────────────────────────────────── */

.login-wrap {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 80vh;
}

.login-card {
    width: 100%;
    max-width: 26rem;
}

/*
 * 로그인 화면에는 셋만 둔다: 회사 이름 · QR · 구글 버튼. 그래서 가운데로 모으고
 * 사이 간격만 정한다.
 */
.login-card__title {
    margin: 0 0 var(--space-5);
    font-size: var(--text-xl);
    text-align: center;
}

.login-card__qr {
    display: flex;
    justify-content: center;
    margin-bottom: var(--space-5);
}

/*
 * QR 은 **화면 크기를 따라간다.** 고정 픽셀로 두면 좁은 화면에서 잘리고 넓은 화면에서
 * 초라하다. 스캔에 필요한 최소 크기(약 160px)는 지킨다.
 */
.login-card__qr svg {
    width: min(60vw, 13rem);
    height: auto;
    min-width: 10rem;
    /* 흰 바탕·검은 모듈이어야 인식된다. `--scan-surface` 는 다크 모드에서도 흰색이다. */
    padding: var(--space-2);
    border-radius: var(--radius);
    background-color: var(--scan-surface);
}

.login-google {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
}

/* ── 출퇴근 ─────────────────────────────────────────────────────── */

.time-clock {
    text-align: center;
}

.time-clock__state {
    margin-bottom: var(--space-1);
    font-size: var(--text-md);
    font-weight: 600;
}

.time-clock__elapsed {
    margin-bottom: var(--space-1);
    font-size: var(--text-2xl);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: var(--leading-tight);
}

.time-clock__since {
    margin-bottom: var(--space-4);
    color: var(--text-muted);
}

.time-clock__button {
    display: block;
    width: 100%;
    max-width: 22rem;
    margin: 0 auto;
    font-size: var(--text-md);
    font-weight: 700;
    letter-spacing: .05em;
}

.time-clock__today-title {
    margin: var(--space-5) 0 var(--space-2);
    text-align: left;
    font-size: var(--text-md);
}

.today-entries {
    margin: 0;
    padding: 0;
    list-style: none;
    text-align: left;
}

.today-entry {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) 0;
    border-bottom: 1px solid var(--border);
}

.today-entry:last-child {
    border-bottom: none;
}

.today-entry__times {
    flex: 1 1 auto;
    font-variant-numeric: tabular-nums;
}

.today-entry__net {
    flex: 0 0 4rem;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* ── 휴게 확인 모달 ─────────────────────────────────────────────── */

.break-preview {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: var(--space-1) var(--space-4);
    margin: 0;
}

.break-preview dt {
    font-weight: 400;
    color: var(--text-muted);
}

.break-preview dd {
    margin: 0;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.break-preview--total dd {
    font-size: var(--text-md);
    font-weight: 600;
}

.break-policy {
    margin: var(--space-4) 0;
    color: var(--text-muted);
    font-size: var(--text-sm);
}

/* ── 요약 타일 ──────────────────────────────────────────────────── */

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

.summary-tile {
    display: flex;
    flex-direction: column;
    gap: var(--space-0);
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background-color: var(--card-bg);
}

/* 주의가 필요한 타일. 테두리만 바꾸면 스캔에서 놓친다 — 틴트를 함께 쓴다. */
.summary-tile--warn {
    border-color: var(--warning-line);
    background-color: var(--warning-tint);
}

.summary-tile__label {
    color: var(--text-muted);
    font-size: var(--text-sm);
}

.summary-tile__value {
    font-size: var(--text-xl);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.summary-tile__sub {
    color: var(--text-muted);
    font-size: var(--text-xs);
}

/* ── 정정요청 ───────────────────────────────────────────────────── */

.comparison--compact {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.comparison__side--requested,
.comparison__requested {
    font-weight: 600;
}

.comparison__diff--plus { color: var(--success-text); }
.comparison__diff--minus { color: var(--danger-text); }

/* 사유 칸은 길다. 목록에서 표를 밀어내지 않게 자른다. */
.reason-cell {
    max-width: 18rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.correction-reason {
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-4);
    border-left: 3px solid var(--accent-line);
    border-radius: 0 var(--radius) var(--radius) 0;
    background-color: var(--surface-2);
    white-space: pre-wrap;
}

/* ── 알림 ───────────────────────────────────────────────────────── */

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

.notification-item {
    padding: var(--space-3) 0;
    border-bottom: 1px solid var(--border);
}

.notification-item:last-child {
    border-bottom: none;
}

/* 읽지 않은 알림은 왼쪽 띠로 구분한다. 굵기만으로 구분하면 스캔이 어렵다. */
.notification-item--unread {
    padding-left: var(--space-3);
    border-left: 3px solid var(--accent);
}

.notification-item__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-2);
}

.notification-item__body {
    margin-top: var(--space-0);
    color: var(--text-muted);
    font-size: var(--text-sm);
}

.notification-item__link {
    display: inline-block;
    margin-top: var(--space-1);
    font-size: var(--text-sm);
}

/* ── 좁은 화면용 카드 목록 (docs/06 §9) ─────────────────────────── */

.employee-cards {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.employee-card {
    display: flex;
    flex-direction: column;
    /* 모바일에서 열이 부풀어 잘리지 않게 한다 (docs/06 §9). */
    align-items: flex-start;
    gap: var(--space-1);
    padding: var(--space-3);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background-color: var(--card-bg);
}

.employee-card__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    gap: var(--space-2);
}

.employee-card__meta {
    color: var(--text-muted);
    font-size: var(--text-sm);
}

.employee-card__actions {
    width: 100%;
    margin-top: var(--space-1);
}

/* ── 지도 · 지오펜스 · 주소 검색 (FR-3.7) ───────────────────────── */

.geofence-map {
    height: 420px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

/* 지오펜스 지도보다 낮다. 폼 한가운데서 화면을 다 먹지 않게 한다. */
.site-map {
    height: 320px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

/* Leaflet 타일은 다크 모드에서도 그대로 둔다. 색을 반전하면 지도가 읽히지 않는다. */
[data-theme="dark"] .geofence-map,
[data-theme="dark"] .site-map {
    filter: none;
}

.geofence-list {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.geofence-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.geofence-row input[type="text"] {
    flex: 1 1 12rem;
    min-width: 8rem;
}

.geofence-row__radius {
    flex: 0 0 6rem;
}

.geofence-row__shape {
    flex: 0 0 auto;
}

.geofence-row__active {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    margin: 0;
}

/* 상태 문구는 두 곳(지오펜스 편집기·주소 검색)에서 같은 모양이어야 한다. */
.geofence-status,
.geocode-status {
    font-size: var(--text-sm);
    color: var(--text-muted);
}

.geocode-status {
    /* 문구가 없을 때도 자리를 지킨다 — 나타날 때 폼이 흔들리지 않게. */
    min-height: 1.25rem;
}

.geofence-status--error,
.geocode-status--error {
    color: var(--danger-text);
    font-weight: 600;
}

/* 후보가 많아도 폼을 밀어내지 않게 스크롤로 가둔다. */
.geocode-results {
    max-height: 14rem;
    overflow-y: auto;
}

.geocode-result {
    font-size: var(--text-sm);
}

/* ── CSV 샘플 ───────────────────────────────────────────────────── */

.csv-sample {
    padding: var(--space-3);
    overflow-x: auto;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background-color: var(--surface-2);
    font-family: var(--font-mono);
    font-size: var(--text-xs);
}

/* ══ 10. 한/영 전환 ═══════════════════════════════════════════════ */

/*
 * 언어가 셋이 되면서 토글에서 목록으로 바꿨다. 항목마다 폼이 하나씩이라(POST + CSRF)
 * `<form>` 이 `<li>` 와 `.dropdown-item` 사이에 끼어든다 — Bootstrap 의 메뉴 레이아웃이
 * 그 중간 요소를 모르므로 `display: contents` 로 없는 것처럼 만든다.
 */
.locale-switch form {
    display: contents;
}

.locale-switch__button {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    /* 목록 항목도 누르는 것이다 (docs/06 §9). */
    min-height: var(--touch-target);
}

/* 현재 언어. 체크 표시가 있어야 목록을 열었을 때 지금 무엇인지 바로 보인다. */
.locale-switch__button.active {
    background-color: var(--accent-tint);
    color: var(--accent-text);
    font-weight: 600;
}

/*
 * 표시 자리를 항상 잡아 둔다. 현재 언어에만 아이콘을 두면 글자가 좌우로 흔들려
 * 어느 줄이 선택됐는지 훑기 어렵다.
 */
.locale-switch__mark {
    flex: 0 0 1rem;
    text-align: center;
}

.locale-switch__button:not(.active) .locale-switch__mark {
    opacity: 0;
}

/* 출퇴근 화면의 현장 선택. 버튼 위에 두고 폭을 버튼과 맞춘다. */
.time-clock__site {
    margin-bottom: var(--space-3);
    text-align: left;
}
