
/* ══════════════════════════════════════════════════════════════════════════
   간격 눈금 (2026-09-04 전수조사) — 2px 격자
   낱값 2,951개·43가지였다. 1~20px 에 96% 가 몰려 있는데 **모든 정수가 쓰였다**
   (3px 133 · 5px 126 · 7px 72 · 9px 125 · 11px 120 · 13px 60 …) — 규칙이 없었다는 뜻이다.
   나란한 카드의 안쪽 여백이 13과 14면 이유는 몰라도 줄이 안 맞아 보인다.

   🚨 홀수는 짝수로 **올린다**(+1px). 내리면 글자가 모서리에 닿을 수 있다.
   🚨 1px 은 그대로 — 여백이 아니라 선 두께 보정이라 2px 로 올리면 어긋난다.
   ══════════════════════════════════════════════════════════════════════════ */
:root{
  --s-0:0; --s-hair:1px;
  --s-1:2px;  --s-2:4px;  --s-3:6px;   --s-4:8px;   --s-5:10px;
  --s-6:12px; --s-7:14px; --s-8:16px;  --s-9:18px;  --s-10:20px;
  --s-12:24px; --s-14:28px; --s-16:32px; --s-20:40px; --s-24:48px;
  --s-28:56px; --s-32:64px;
  /* 🚨 **레이아웃 상수는 격자에 넣지 않는다.** 여백 리듬이 아니라 다른 요소의 크기를
     따라가는 값이라, 2px 격자로 반올림하면 그 요소와 어긋난다 — 실제로 사이드바 폭
     212px 이 격자 최대(64px)로 뭉개져 **본문이 사이드바 밑으로 들어갔다**(2026-09-04). */
  --nav-w:212px;       /* 사이드바 폭 — 본문 왼쪽 여백이 이걸 따라간다 */
  --nav-w-mini:84px;   /* 좁은 사이드바 */
  --pg-bottom:96px;    /* 본문 아래 여유(하단 바 가림 방지) */
  --anchor-top:70px;   /* 앵커로 이동했을 때 앱바에 안 가리게 */
}

/* ══════════════════════════════════════════════════════════════════════════
   색 눈금 (2026-09-04 전수조사)
   템플릿에 하드코딩된 색이 332곳·75가지였다. 두 가지가 **기능 문제**였다:
    ① 테마 토큰과 같은 색을 손으로 박은 20곳 — 다크모드·브랜드 변경에 안 따라온다.
    ② 근태 상태색이 화면마다 복사돼 **같은 상태가 다른 색**이었다(사무실·이동중·휴게·통근).
       manage_work_audit 은 한 화면 안에서도 위 띠와 아래 막대가 달랐다.
       상태를 색으로 읽는 화면에서 색이 어긋나면 미관이 아니라 **오독**이다.
   ══════════════════════════════════════════════════════════════════════════ */
:root{
  --on-accent:#fff;          /* 색 위에 얹는 글자 */
  /* 분류·차트 팔레트 — 이름이 **색 자체**를 말한다. 어디에 써도 거짓말하지 않는다. */
  --c-blue:#3B82F6; --c-green:#10B981; --c-amber:#F59E0B; --c-red:#EF4444;
  --c-violet:#8B5CF6; --c-pink:#EC4899; --c-cyan:#06B6D4; --c-lime:#84CC16;
  --c-teal:#14B8A6; --c-slate:#94A3B8; --c-slate-2:#CBD5E1;
  /* 근태·근무 상태 — 이 색이 곧 범례다. 화면마다 복사하지 말 것.
     🚨 **팔레트를 가리키게 둔다.** 처음엔 상태 토큰을 색 전체에 일괄로 갈아끼웠는데,
        「퇴근 완료」 막대에 통근색이, 「자동퇴근」 표시에 재택색이 붙었다 — 색은 같아도
        **이름이 사실과 달라진다.** 그러면 다음 사람이 재택색을 바꿀 때 엉뚱한 게 같이 바뀐다.
        상태 토큰은 **상태를 칠하는 자리에서만** 쓴다. */
  --att-field:var(--accent);      /* 현장 */
  --att-disp:var(--c-teal);       /* 출장·파견 */
  --att-office:var(--ok);         /* 사무실 */
  --att-home:var(--c-violet);     /* 재택 */
  --att-move:var(--c-blue);       /* 이동중 */
  --att-brk:var(--sub);           /* 휴게 */
  --att-commute-a:var(--c-slate); /* 통근(빗금) */
  --att-commute-b:var(--c-slate-2);
  /* 🔑 빗금 **무늬까지** 토큰으로. 색만 맞춰 두니 간격이 3px·4px 로 갈렸다 —
     조각으로 나눠 두면 그 조각마다 또 갈라진다. 쓰는 자리는 이 한 줄만 참조한다. */
  --att-commute-bg:repeating-linear-gradient(45deg,var(--att-commute-a),
    var(--att-commute-a) 3px,var(--att-commute-b) 3px,var(--att-commute-b) 6px);
  /* 🔑 빗금 **무늬까지** 토큰으로. 색만 맞춰 두니 간격이 3px·4px 로 갈렸다 —
     조각으로 나눠 두면 그 조각마다 또 갈라진다. 쓰는 자리는 한 줄만 참조한다. */
  --att-commute-bg:repeating-linear-gradient(45deg,var(--att-commute-a),
    var(--att-commute-a) 3px,var(--att-commute-b) 3px,var(--att-commute-b) 6px);
}

/* ══════════════════════════════════════════════════════════════════════════
   모서리·굵기 눈금 (2026-09-04 전수조사)
   폰트와 같은 문제였다 — 모서리 **22가지**(367곳) · 굵기 **8가지**(709곳)가 화면마다
   손으로 박혀 있었다. 나란히 놓인 카드의 모서리가 10과 12로 다르면 이유는 몰라도
   "안 맞다"고 느껴진다. 그게 통일성이 없다는 말의 실체다.

   🚨 지배적인 값(5·9·10·12)은 **그대로 두고** 주변 값만 흡수했다. 눈금을 만드는 일과
      화면을 바꾸는 일은 다르다 — 한 번에 하면 어색해졌을 때 원인을 못 가린다.
   ══════════════════════════════════════════════════════════════════════════ */
:root{
  --r-xs:6px;      /* 칩·점·작은 표식 */
  --r-sm:9px;      /* 배지·작은 버튼 */
  --r-md:10px;     /* 버튼·입력 */
  --r-lg:12px;     /* 카드 */
  --r-xl:16px;     /* 모달·시트 */
  --r-pill:999px;  /* 알약 */
  --w-normal:400; --w-medium:500; --w-semibold:600; --w-bold:700; --w-black:800;
}

/* ══════════════════════════════════════════════════════════════════════════
   역할이 같으면 크기도 같다 (사장님 2026-09-04 "유형이나 담당이나 폰트 크기 통일성도 아직")
   px→토큰 치환은 **원래 있던 불일치를 토큰으로 옮겼을 뿐**이었다. 통일은 값이 아니라
   **역할**로 잡아야 한다. 한 줄 안에 표식·라벨·컨트롤이 섞여 있으면 셋이 각자 크기를
   가져가는 게 아니라, 표식끼리 · 컨트롤끼리 같아야 눈이 편하다.

     표식(배지·상태칩·pill)  --fs-xs
     보조 라벨·캡션           --fs-sm
     본문·버튼                --fs-base
     입력·선택(컨트롤)        --fs-md   (모바일은 --fs-field=16px)

   🚨 그리고 **인라인 font-size 가 컴포넌트를 덮지 못하게** 걷어냈다(324곳).
      인라인이 클래스를 이기므로, 하나만 남아도 그 화면만 어긋난다 — 통일은 규칙이 아니라
      구조로 지켜야 한다. 크기를 달리해야 하면 변형 클래스를 만들 것.
   ══════════════════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════════════════
   타이포 눈금 (사장님 2026-09-04: "고정으로 가지말고 어플처럼 보이게")
   손으로 박은 px 이 화면마다 제각각이었다 — 9px~34px **22가지**(CSS 140 + 템플릿 1,339).
   눈금이 없으니 어디를 봐도 어긋나 보이고, 모바일에서 입력칸만 16px 로 올리니 주변 12px 과
   벌어져 더 도드라졌다. 값을 토큰으로 바꾸면 ①한 곳에서 조절되고 ②화면 폭에 따라 단이
   통째로 움직인다 — 그게 "고정이 아니게" 되는 것이다.

   🚨 데스크톱 값은 **원래 가장 흔하던 값 그대로** 잡았다. 눈금을 만드는 것과 화면을 바꾸는 건
      다른 일이라 한 번에 하면 무엇이 원인인지 못 가린다.
   ══════════════════════════════════════════════════════════════════════════ */
:root{
  --fs-micro:10.5px;  /* 미세 라벨·단위 */
  --fs-xs:11.5px;     /* 보조 설명 */
  --fs-sm:12px;       /* 캡션·배지 */
  --fs-base:13px;     /* 본문 */
  --fs-md:13.5px;     /* 표·버튼 */
  --fs-lg:15px;       /* 소제목 */
  --fs-xl:22px;       /* 페이지 제목 */
  --fs-2xl:26px;      /* 큰 숫자 */
  --fs-3xl:34px;      /* 대표 지표 */
  /* 입력칸은 따로 둔다 — 아래 모바일 규칙에서 16px 로 올려야 iOS 가 화면을 확대하지 않는다 */
  --fs-field:13.5px;
}
/* 손에 쥐고 보는 화면은 한 단 크게. 앱이 웹보다 글자가 큰 건 취향이 아니라
   **팔 길이만큼 멀고 흔들리기 때문**이다. */
@media(max-width:768px){
  :root{
    /* 🚨 **작은 글씨는 키우고 큰 글씨는 줄인다.** 처음엔 단을 통째로 키웠는데, 원래 이 디자인은
       모바일에서 제목을 일부러 줄이고 있었다(page-title 22→20). 통째로 키우면 좁은 화면을
       제목이 잡아먹고 정작 읽을 본문은 그대로다 — 앱이 촘촘해 보이는 건 본문이 크고 제목이
       과하지 않아서다. 위계를 좁히는 쪽이 맞다. */
    --fs-micro:11.5px; --fs-xs:12.5px; --fs-sm:13px; --fs-base:14px; --fs-md:14.5px;
    --fs-lg:16px; --fs-xl:20px; --fs-2xl:22px; --fs-3xl:27px;
    /* 🚨 16px 미만 입력칸을 누르면 iOS 가 화면을 확대하고 되돌리지 않는다.
       주변 본문이 14.5px 라 16px 입력이 자연스럽게 얹힌다 — 12px 옆의 16px 이 튀던 자리다. */
    --fs-field:16px;
  }
}
:root{
  --accent:#E8642A; --accent-weak:rgba(232,100,42,.12); --accent-dark:#c9491a;
  --bg:#f4f5f7; --card:#ffffff; --text:#1a1d24; --sub:#677080; --border:#ebedf1;
  --radius:18px; --shadow:0 1px 3px rgba(16,24,40,.06),0 4px 12px rgba(16,24,40,.08);
  --shadow-lift:0 2px 6px rgba(16,24,40,.10),0 12px 28px rgba(16,24,40,.14);
  --ok:#10B981; --warn:#F59E0B; --err:#EF4444; --hair:#f0f2f5;
  /* ♿ 글자용 상태색(2026-09-27 대비 측정) — --ok/--err 는 **채우기**(점·막대·배경)용이라 그대로 두고,
     글자로 쓸 땐 테마별로 4.5:1 을 넘는 값을 따로 쓴다. 한 색으로 두 테마를 다 통과하는 값은 없다
     (#10B981: 흰 배경 2.54 / 다크 카드 6.34). --sub 도 #737c87(4.23) → #677080(4.99). */
  --ok-t:#047857; --err-t:#B91C1C; --warn-t:#92400E;
  --accent-t:#C2410C;  /* 작은 주황 «글자»용(5.18). 면·버튼·점은 --accent(#E8642A, 3.34) 그대로 — 9/27 사장님 B안 */
  --st-ok:#047857; --st-err:#B91C1C; --st-warn:#92400E; --st-pur:#7C3AED; --st-blue:#1D4ED8; --st-slate:#64748B; --st-gray:#6B7280;
  /* 🎬 감속 곡선 — iOS 가 시트·화면 전환에 쓰는 모양(2026-09-21 적용).
     이전 값은 구글 머티리얼 표준 cubic-bezier(.4,0,.2,1) 로 시작·끝이 **대칭**이라
     차분하지만 기계적으로 읽혔다. 새 값은 **확 출발해 길게 안착**하는 비대칭이라
     같은 260ms 인데도 더 빠르고 부드럽게 느껴진다 — «샥» 하는 느낌의 정체가 이 비대칭이다.
     🔑 되돌리려면 이 한 줄만 옛 값으로. 39곳이 이 토큰을 가리킨다.
     (튀는 맛이 필요한 면은 --spring 이 따로 맡는다 — 모달·시트·서랍) */
  --ease:cubic-bezier(.32,.72,0,1); --spring:cubic-bezier(.34,1.56,.64,1);
  /* 닫힘 전용(2026-09-24) — --ease(iOS 감속)는 앞에 몰려 닫힘이 ¼ 지점에 이미 78% 사라졌다(«툭»).
     가감속이면 ¼ 12% · ½ 50% · ¾ 88% 로 고르게 빠진다. 열림은 그대로 --ease/--spring. */
  --ease-exit:cubic-bezier(.45,0,.55,1);
  /* ── 모션 눈금 (2026-09-21) ────────────────────────────────────────────
     곡선(--ease/--spring)은 이미 토큰이었는데 **지속시간만 21가지**로 흩어져 있었다
     (.1 .12 .13 .14 .15 .16 .2 .22 .25 .26 .28 .3 …). 같은 성격의 움직임이 화면마다
     미세하게 다른 속도로 도니 «앱»이 아니라 «웹»으로 읽힌다 — 리듬이 없기 때문이다.
     4단으로 줄인다. 규칙: **가까운 쪽으로, 동률이면 느린 쪽**.
       d-1 누름·색·호버 같은 미세 반응 · d-2 작은 이동/회전 · d-3 모달·시트 등 면(面)
       d-4 큰 서랍처럼 거리가 먼 것
     🚨 **300ms 초과는 격자에 넣지 않는다** — 로딩바 페이드(.4s)·긴 여운(.5s)은 리듬이 아니라
        «의도적으로 느린» 값이다. 격자로 당기면 그 의도가 사라진다(레이아웃 상수를 간격
        격자에 넣지 않는 것과 같은 이유). */
  --d-1:120ms; --d-2:180ms; --d-3:260ms; --d-4:380ms;
  --flt-h:46px;      /* 폰 목록 «접힌 필터» 버튼이 차지하는 총 높이(실측) — 자리 예약에 쓴다 */
  --sb-bg:#ffffff; --sb-border:var(--border); --sb-brand:#1a1d24; --sb-brand-sub:rgba(26,29,36,.42);
  --sb-group:rgba(26,29,36,.4); --sb-text:rgba(26,29,36,.62); --sb-text-hover:#1a1d24; --sb-hover-bg:rgba(26,29,36,.045);
  /* 🚨 여기 있던 **옛 타이포 스케일(2026-07)** 을 걷어냈다(2026-09-07).
     파일 뒤쪽에 있다는 이유만으로 위에 새로 만든 눈금의 xs·sm·base·lg·xl **다섯 개를 덮고**
     있었다 — 모바일 재정의까지 이겨서, 제목을 22→20px 로 낮춘 것도 내내 22px 였고
     상태 드롭다운이 17px 로 남아 있었다. 규칙이 안 먹는 게 아니라 **값이 덮여 있었다.**
     `--fs-body` 는 쓰는 데가 0곳이라 함께 정리. 타이포 눈금은 파일 상단 한 곳에만 있다. */
}
[data-theme="dark"] input[type="date"],[data-theme="dark"] input[type="time"],[data-theme="dark"] input[type="month"]{color-scheme:dark}
.att-range{height:33.5px;box-sizing:border-box;transition:border-color var(--d-1),box-shadow var(--d-1)}
.att-range:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-weak)}
.att-range input[type="date"]{font-size:var(--fs-sm);padding:var(--s-1) var(--s-1);border:none;background:transparent;color:var(--text);font-family:inherit;min-width:104px}
.att-range input[type="date"]:focus{outline:none}
.att-range-go{font-size:var(--fs-sm);font-weight:var(--w-semibold);height:26px;padding:0 var(--s-6);border:none;border-radius:var(--r-sm);background:var(--accent);color:#fff;cursor:pointer;transition:background var(--d-1)}
.att-range-go:hover{background:var(--accent-dark)}
[data-theme="dark"]{
  --bg:#15171c; --card:#1e2129; --text:#e7e9ee; --sub:#9aa2ad; --border:#2b2f39; --hair:#252932;
  --ok-t:#34D399; --err-t:#F87171; --warn-t:#F59E0B; --accent-t:#F08050;
  --st-ok:#10B981; --st-err:#F87171; --st-warn:#F59E0B; --st-pur:#A78BFA; --st-blue:#60A5FA; --st-slate:#94A3B8; --st-gray:#9CA3AF;
  --accent-weak:rgba(232,100,42,.18);
  --shadow:0 1px 2px rgba(0,0,0,.3),0 8px 24px rgba(0,0,0,.35);
  --shadow-lift:0 6px 16px rgba(0,0,0,.4),0 20px 48px rgba(0,0,0,.5);
  --sb-bg:#16181d; --sb-border:rgba(255,255,255,.05); --sb-brand:#e6e8ec; --sb-brand-sub:rgba(255,255,255,.45);
  --sb-group:rgba(255,255,255,.38); --sb-text:rgba(255,255,255,.72); --sb-text-hover:#fff; --sb-hover-bg:rgba(255,255,255,.06);
}
*{box-sizing:border-box}
body{margin:0;display:flex;min-height:100vh;background:var(--bg);color:var(--text);
  font-family:"Pretendard Variable",Pretendard,-apple-system,system-ui,sans-serif;
  font-size:var(--fs-md);line-height:1.45;
  letter-spacing:-.01em;-webkit-font-smoothing:antialiased}
a{color:inherit;text-decoration:none}
code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.9em;background:var(--accent-weak);color:var(--accent-t);padding:var(--s-hair) var(--s-3);border-radius:var(--r-xs)}

/* 사이드바 */
.sidebar{position:fixed;left:0;top:0;bottom:0;width:84px;background:var(--sb-bg);
  display:flex;flex-direction:column;z-index:50;border-right:1px solid var(--sb-border)}
.sbrand{padding:var(--s-9) 0 var(--s-6);display:flex;flex-direction:column;align-items:center;gap:6px;color:var(--sb-brand)}
.sbrand b{font-size:var(--fs-sm);font-weight:var(--w-black);color:var(--sb-brand)}
.logo-dot{width:30px;height:30px;border-radius:var(--r-sm);
  background:linear-gradient(135deg,var(--accent),#f7955e);box-shadow:0 4px 12px rgba(232,100,42,.4)}
.navwrap{flex:1;display:flex;flex-direction:column;padding-top:var(--s-3);overflow-y:auto;opacity:0}
.navi{display:flex;flex-direction:column;align-items:center;gap:5px;padding:var(--s-6) var(--s-2);
  color:rgba(255,255,255,.5);font-size:var(--fs-micro);font-weight:var(--w-semibold);border-left:3px solid transparent;cursor:pointer;transition:color var(--d-2) var(--ease),background var(--d-2) var(--ease)}
.navi svg{width:22px;height:22px;transition:transform var(--d-2) var(--spring)}
.navi:hover{color:var(--sb-text-hover);background:var(--sb-hover-bg)}
.navi:hover svg{transform:translateY(-2px)}
.navi.on{color:var(--accent-t);border-left-color:var(--accent);background:var(--accent-weak)}

/* 콘텐츠 */
.content{margin-left:var(--nav-w-mini);flex:1;display:flex;flex-direction:column;min-width:0;
  /* 우하단 AI 비서 FAB(.assistant-fab, 52px + bottom 22px, z-index 70)이 페이지 **마지막 요소를 덮는다**
     — 정기점검 「점검 완료」 버튼이 가려져 못 누르는 일이 있었다(2026-08-24 사장님).
     모바일엔 탭바용 여백이 있었지만 데스크톱엔 없었다. 전역으로 확보한다. */
  padding-bottom:var(--pg-bottom)}
.appbar{display:flex;align-items:center;justify-content:space-between;
  background:var(--card);border-bottom:1px solid var(--border);padding:var(--s-6) var(--s-12);position:sticky;top:0;z-index:40}
.appbar-title{font-size:var(--fs-md);font-weight:var(--w-black)}
.appbar-right{display:flex;align-items:center;gap:12px}
.user-chip{font-size:var(--fs-base);color:var(--sub)}
.icon-btn{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;
  border:1px solid var(--border);border-radius:var(--r-md);background:var(--card);color:var(--sub);cursor:pointer;transition:var(--d-2) var(--ease)}
.icon-btn:hover{color:var(--accent-t);border-color:var(--accent);transform:translateY(-1px)}
.icon-btn svg{width:18px;height:18px}
.icon-btn.spin svg{animation:gwSpin .7s linear infinite}
.linkbtn{background:none;border:1px solid var(--border);color:var(--sub);cursor:pointer;font-size:var(--fs-sm);font-family:inherit;padding:var(--s-3) var(--s-7);border-radius:var(--r-sm);text-decoration:none;transition:border-color var(--d-1) var(--ease),color var(--d-1) var(--ease)}
.linkbtn:hover{border-color:var(--accent);color:var(--accent-t)}
.main{padding:var(--s-12);flex:1}

/* 페이지·카드 */
.page-title{font-size:var(--fs-xl);font-weight:var(--w-black);letter-spacing:-.03em;margin:0 0 var(--s-2)}
/* 드로어 안에 얹힌 상세 — 제목이 본문을 누르지 않게 한 단 낮춘다.
   인라인으로 크기를 박지 않고 **변형 클래스**로 둔다: 인라인은 컴포넌트를 이겨서
   "여기만 다른" 자리를 만든다(그게 통일이 깨지는 방식이다). */
.page-title.page-title-sm{font-size:var(--fs-lg)}
.page-sub{color:var(--sub);font-size:var(--fs-base);margin:0 0 var(--s-8)}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:14px}
/* 🎨 「떠 보이게」(2026-09-07 사장님 선택) — 테두리와 그림자를 **같이** 쓰던 게 옛날 감각이었다.
   테두리를 없애고 그림자만 남긴다. 그림자는 넓고 흐린 것(8px 24px)에서 **짧고 진한 것**으로 —
   그래야 종이처럼 떠 보인다.
   🚨 border 를 **지우지 않고 투명**으로 둔다. 지우면 카드마다 2px 씩 줄어 배치가 밀린다. */
.card{background:var(--card);border:1px solid transparent;border-radius:var(--radius);
  padding:var(--s-9);box-shadow:var(--shadow);transition:transform var(--d-2) var(--ease),box-shadow var(--d-2) var(--ease)}
/* 어두운 화면에선 그림자가 거의 안 보인다 — 머리카락 선으로 경계를 남긴다 */
[data-theme="dark"] .card{border-color:var(--border)}
.card.stat:hover{transform:translateY(-3px);box-shadow:var(--shadow-lift)}
.card-label{font-size:var(--fs-sm);font-weight:var(--w-bold);color:var(--sub);margin-bottom:var(--s-4)}
.card-big{font-size:var(--fs-2xl);font-weight:var(--w-black);letter-spacing:-.02em}
.card-big.tone-ok{color:var(--ok-t)}.card-big.tone-warn{color:var(--warn-t)}.card-big.tone-err{color:var(--err-t)}
.card-sub{font-size:var(--fs-sm);color:var(--sub);margin-top:var(--s-1)}
.roadmap{margin:var(--s-4) 0 0;padding-left:var(--s-9);line-height:1.9;font-size:var(--fs-base)}
.roadmap b{color:var(--accent-t)}
.demo-row{display:flex;flex-wrap:wrap;gap:9px;align-items:center}

/* 배지·버튼 */
.badge{display:inline-flex;align-items:center;gap:5px;font-size:var(--fs-sm);font-weight:var(--w-bold);
  padding:var(--s-2) var(--s-5);border-radius:var(--r-pill);background:var(--hair);color:color-mix(in srgb,var(--text) 75%,var(--card))}
/* 9/27 디자인 전수조사: 배지 기본이 주황이라 유형·용도·상태 칩이 전부 주황 → 강조가 사라졌다. 주황은 뜻이 있을 때만 .accent */
.badge.accent{background:var(--accent-weak);color:var(--accent-t)}
.dot{width:8px;height:8px;border-radius:50%}
.dot.ok{background:var(--ok)}.dot.warn{background:var(--warn)}.dot.err{background:var(--err)}
.btn{display:inline-flex;align-items:center;gap:6px;background:var(--accent);color:#fff;font-weight:var(--w-bold);
  font-size:var(--fs-base);line-height:1.45;padding:var(--s-4) var(--s-8);border:1px solid transparent;border-radius:var(--r-md);cursor:pointer;font-family:inherit;
  transition:transform var(--d-1) var(--ease),background var(--d-2) var(--ease),box-shadow var(--d-2) var(--ease)}
.btn:hover{background:var(--accent-dark);box-shadow:0 4px 14px rgba(232,100,42,.28)}
.btn:active{transform:translateY(1px) scale(.98)}
.btn.ghost{background:var(--card);color:var(--text);border:1px solid var(--border);box-shadow:none}
.btn.ghost:hover{border-color:var(--accent);color:var(--accent-t)}
.btn.danger{background:#DC2626;color:#fff}.btn.danger:hover{background:#B91C1C}

/* 폼 필드 */
.field-label{display:block;font-size:var(--fs-sm);font-weight:var(--w-bold);color:var(--sub);margin:var(--s-5) 0 var(--s-3)}
/* 입력요소 자체에 .field (표준 A: field-label + input.field). label.field(B 다수)는 아래 wrapper 규칙 적용 */
input.field,select.field,textarea.field{width:100%;border:1px solid var(--border);border-radius:var(--r-md);padding:var(--s-5) var(--s-6);font-size:var(--fs-md);
  background:var(--bg);color:var(--text);font-family:inherit;transition:border-color var(--d-1) var(--ease),box-shadow var(--d-1) var(--ease)}
select.field{-webkit-appearance:none;appearance:none;padding-right:var(--s-16);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23999' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 11px center}
input.field:focus,select.field:focus,textarea.field:focus{outline:0;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-weak)}

/* 드롭다운 */
.dropdown{position:relative}
.dropdown-pop{position:absolute;top:calc(100% + 6px);left:0;min-width:170px;background:var(--card);
  border:1px solid var(--border);border-radius:var(--r-lg);box-shadow:var(--shadow-lift);padding:var(--s-3);z-index:70}
.dropdown-item{display:block;padding:var(--s-4) var(--s-6);border-radius:var(--r-sm);font-size:var(--fs-base);cursor:pointer}
.dropdown-item:hover{background:var(--accent-weak);color:var(--accent-t)}

/* 모달 (전역·스코프 없음 = 어디서든 재사용) */
.modal-bg{position:fixed;inset:0;background:rgba(16,20,28,.44);backdrop-filter:blur(2px);
  display:flex;align-items:center;justify-content:center;z-index:100;padding:var(--s-10)}
.modal{background:var(--card);border:1px solid var(--border);border-radius:var(--r-xl);padding:var(--s-12);
  width:420px;max-width:100%;box-shadow:var(--shadow-lift);animation:modalIn var(--d-3) var(--spring)}
.modal.modal-sm{width:340px}

/* 🎬 닫힐 때도 움직인다(2026-09-21). 지금까지 **열 때만** 애니메이션이 있고 닫으면 툭 사라졌다.
   앱은 들어온 길로 되돌아 나간다 — 그게 «어디로 갔는지»를 알려준다.
   🚨 `.modal-bg.show` 클래스는 CSS 가 **아예 없었다.** gwConfirm 이 show 를 떼고 200ms 기다렸다
      지웠는데, 대응 스타일이 없어 «아무 변화 없이 200ms 멈췄다 사라지는» 상태였다.
      (열림 상태를 .show 로 표현하지 않고, 닫힘만 .gw-closing 으로 표시한다 — 기존 마크업이
       .show 없이도 떠 있기 때문에 .show 에 의존하면 그 모달들이 통째로 안 보인다.) */
.modal-bg{transition:opacity var(--d-2) var(--ease)}
.modal-bg.gw-closing{opacity:0;pointer-events:none;transition:opacity var(--d-3) var(--ease-exit)}
.modal-bg.gw-closing .modal{animation:modalOut var(--d-3) var(--ease-exit) forwards}
@keyframes modalOut{to{opacity:0;transform:translateY(6px) scale(.98)}}
.fdrawer-bg.gw-closing{opacity:0;pointer-events:none;transition:opacity var(--d-3) var(--ease-exit)}
.fdrawer-bg.gw-closing .fdrawer{animation:fdrawerOut var(--d-3) var(--ease-exit) forwards}
@keyframes fdrawerOut{to{transform:translateX(28px);opacity:0}}
@media(prefers-reduced-motion:reduce){
  .modal-bg.gw-closing .modal,.fdrawer-bg.gw-closing .fdrawer{animation:none}
}

/* 폼 드로어 — 항목 많은 폼을 오른쪽에서 밀어 올린다(가운데 모달이 답답한 경우).
   🚨 이름을 .drawer 로 하면 안 된다 — 고객사 상세의 스플릿 드로어(.drawer/.drawer-bg, 아래쪽)와
   충돌해 그쪽 배경에 display:flex·backdrop-filter 가 새어 화면이 깨진다(2026-08-12 실사고). */
.fdrawer-bg{position:fixed;inset:0;background:rgba(16,20,28,.44);backdrop-filter:blur(2px);
  z-index:100;display:flex;justify-content:flex-end}
.fdrawer{background:var(--card);border-left:1px solid var(--border);width:min(460px,100vw);height:100%;
  overflow-y:auto;padding:var(--s-12) var(--s-14) calc(var(--s-14) + env(safe-area-inset-bottom));
  box-shadow:-18px 0 56px rgba(0,0,0,.16);animation:fdrawerIn var(--d-3) var(--spring,ease)}
.fdrawer h3{margin:0 0 var(--s-3);font-size:var(--fs-lg);font-weight:var(--w-black)}
@keyframes fdrawerIn{from{transform:translateX(28px);opacity:.5}to{transform:none;opacity:1}}
@media(max-width:640px){.fdrawer{width:100%;border-left:0}}
@media (prefers-reduced-motion: reduce){.fdrawer{animation:none}}
.modal h3{margin:0 0 var(--s-3);font-size:var(--fs-lg);font-weight:var(--w-black)}
.modal-sub{color:var(--sub);font-size:var(--fs-base);margin:0 0 var(--s-3);line-height:1.5}
.modal-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:var(--s-9)}
@keyframes modalIn{from{opacity:0;transform:translateY(10px) scale(.97)}to{opacity:1;transform:none}}

/* 토스트 */
.toast-wrap{position:fixed;top:60px;left:50%;transform:translateX(-50%);z-index:200;
  display:flex;flex-direction:column;gap:8px;align-items:center;pointer-events:none}
.toast{background:#23262e;color:#fff;font-size:var(--fs-base);font-weight:var(--w-semibold);padding:var(--s-6) var(--s-9);border-radius:var(--r-lg);
  box-shadow:0 8px 28px rgba(0,0,0,.28);opacity:0;transform:translateY(-14px);
  transition:opacity var(--d-3) var(--ease),transform var(--d-3) var(--spring);max-width:80vw}
.toast.show{opacity:1;transform:none}
.toast-ok{background:#0f9d68}.toast-err{background:#d33f3f}
/* 작업 알림(gwTask) — 도는 점 + 진행 막대. 끝나면 ok/err 로 바뀐다 */
.toast-task{display:flex;align-items:center;gap:var(--s-5);flex-wrap:wrap}
.toast-spin{display:none;width:14px;height:14px;border-radius:50%;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;animation:gw-spin .8s linear infinite;flex:none}
.toast-task .toast-spin{display:inline-block}
.toast-bar{flex:1 0 100%;height:3px;border-radius:var(--r-pill);background:rgba(255,255,255,.2);overflow:hidden}
.toast-bar i{display:block;height:100%;width:0;background:#fff;transition:width var(--d-2) linear}
.toast-ok .toast-bar,.toast-err .toast-bar{display:none}
@keyframes gw-spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.toast-spin{animation-duration:2.4s}}
@media(max-width:768px){
  /* 🚨 `top:64px` 는 앱바 바로 아래 = **페이지 제목 자리**였다(2026-09-21 실기기: 「새로고침했어요」가
     「기술지원 / 내 티켓 12건」을 덮었다). 알림이 내용을 가리면 그건 알림이 아니라 방해다.
     앱 관례대로 아래로 내린다 — 탭바(64) + 비서 FAB(52) 위. FAB 은 오른쪽, 토스트는 가운데라
     같은 높이면 겹친다. */
  .toast-wrap{top:auto;bottom:calc(var(--s-32) + 52px + var(--s-6) + env(safe-area-inset-bottom))}
  /* 위치를 내렸으면 **들어오는 방향도** 바꿔야 한다 — 아래에 뜨는데 위에서 내려오면 어색하다.
     (.toast.show 가 transform:none 으로 덮으므로 최종 위치는 그대로다) */
  .toast{transform:translateY(14px)}
}

/* 스크롤 리빌 */
[data-reveal]{opacity:0;transform:translateY(14px);transition:opacity .5s var(--ease),transform .5s var(--ease)}
[data-reveal].revealed{opacity:1;transform:none}

/* 로그인 — 표현력 있는 메시 그라디언트 배경 */
.login-body{display:flex;align-items:center;justify-content:center;min-height:100vh;background:var(--bg);position:relative;overflow:hidden}
.login-mesh{position:absolute;inset:-20%;z-index:0;filter:blur(60px);opacity:.9;
  background:
    radial-gradient(38% 42% at 20% 24%,rgba(232,100,42,.42),transparent 60%),
    radial-gradient(34% 40% at 82% 30%,rgba(247,149,94,.34),transparent 62%),
    radial-gradient(46% 46% at 62% 84%,rgba(232,100,42,.24),transparent 60%);
  animation:mesh 18s ease-in-out infinite alternate}
@keyframes mesh{
  0%{transform:translate3d(0,0,0) scale(1)}
  50%{transform:translate3d(2%,-2%,0) scale(1.08)}
  100%{transform:translate3d(-2%,2%,0) scale(1.04)}}
.login-card{position:relative;z-index:1;background:var(--card);border:1px solid var(--border);border-radius:var(--r-xl);
  padding:var(--s-20) var(--s-20);width:372px;max-width:90vw;text-align:center;box-shadow:var(--shadow-lift);
  animation:cardIn .5s var(--spring)}
@keyframes cardIn{from{opacity:0;transform:translateY(16px) scale(.98)}to{opacity:1;transform:none}}
.login-logo{display:flex;justify-content:center;margin-bottom:var(--s-8)}
.login-logo .logo-dot{width:48px;height:48px;border-radius:var(--r-lg);animation:float 4s ease-in-out infinite}
@keyframes float{0%,100%{transform:translateY(0)}50%{transform:translateY(-6px)}}
.login-title{font-size:var(--fs-xl);font-weight:var(--w-black);margin:0 0 var(--s-3);letter-spacing:-.03em}
.login-sub{color:var(--sub);font-size:var(--fs-base);margin:0 0 var(--s-12);line-height:1.5}
.google-btn{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;
  padding:var(--s-6);border:1px solid var(--border);border-radius:var(--r-lg);background:var(--card);
  font-weight:var(--w-bold);font-size:var(--fs-md);cursor:pointer;transition:var(--d-2) var(--ease)}
.google-btn:hover{border-color:var(--accent);box-shadow:0 6px 18px rgba(232,100,42,.16);transform:translateY(-1px)}
.login-foot{color:var(--sub);font-size:var(--fs-xs);margin:var(--s-9) 0 0}

/* 모션 감소 접근성 — 애니메이션 최소화 */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
  [data-reveal]{opacity:1!important;transform:none!important}
}


/* ── 관리자 화면 공용: 툴바·테이블 ── */
.page-head{display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:var(--s-6)}  /* 9/27: 제목 아래 ~40px 과함 → 줄임 */
.toolbar{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin:var(--s-9) 0 var(--s-7)}
.toolbar .spacer{flex:1}
.search{display:flex;align-items:center;gap:7px;border:1px solid var(--border);border-radius:var(--r-md);padding:0 var(--s-6);background:var(--card);transition:border-color var(--d-1) var(--ease)}
.search:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-weak)}
.search input{border:0;outline:0;background:none;padding:var(--s-5) 0;font-size:var(--fs-base);color:var(--text);font-family:inherit;flex:1;min-width:0}
.search svg{width:15px;height:15px;color:var(--sub)}

.table-wrap{background:var(--card);border:1px solid var(--border);border-radius:var(--radius);overflow:auto;box-shadow:var(--shadow)}
table.table{width:100%;border-collapse:collapse;font-size:var(--fs-base)}
.table thead th{text-align:left;font-size:var(--fs-sm);font-weight:var(--w-bold);color:var(--sub);padding:var(--s-6) var(--s-8);border-bottom:1px solid var(--border);background:var(--bg)}
.table tbody td{padding:var(--s-6) var(--s-8);border-bottom:1px solid var(--border)}
.table tbody tr:last-child td{border-bottom:0}
.table tbody tr{transition:background var(--d-1) var(--ease)}
.table tbody tr:hover{background:var(--accent-weak)}
/* 🚨 크기가 없었다 — 부모에서 상속하니 **같은 상태 칩이 화면마다 다른 크기**로 떴다.
   배지와 같은 역할(한 단어짜리 표식)이라 같은 단을 쓴다. */
.status{display:inline-flex;align-items:center;gap:7px;font-weight:var(--w-semibold);font-size:var(--fs-sm)}  /* 9/27: 11.5→12px(본문 최소) */
/* 메타 줄의 보조 라벨(「유형」·「고객사 변경」 등) — 값 옆에 붙는 설명. 인라인으로 두면
   화면마다 제각각이 된다(실제로 같은 「유형」이 편집 가능/불가에 따라 크기가 달랐다). */
.meta-label{font-size:var(--fs-sm);color:var(--sub);font-weight:var(--w-semibold)}
.muted{color:var(--sub)}
.dot.accent{background:var(--accent)}
.dot.mute{background:var(--sub)}


/* ── 로고 (온길 마크) ── */
.sbrand{text-decoration:none}
.sbrand .logo{height:38px;width:auto;display:block;filter:drop-shadow(0 3px 8px rgba(232,100,42,.32))}
.login-logo .logo-img{width:72px;height:72px;display:block;border-radius:var(--r-xl);box-shadow:0 10px 30px rgba(232,100,42,.28);animation:float 4s ease-in-out infinite}

.table .num{text-align:right;font-variant-numeric:tabular-nums}


/* 알림 배너 */
.banner{padding:var(--s-6) var(--s-8);border-radius:var(--r-lg);font-size:var(--fs-base);font-weight:var(--w-semibold);margin-bottom:var(--s-8)}
.banner.ok{background:rgba(16,185,129,.12);color:#0f9d68}
.banner.err{background:rgba(239,68,68,.12);color:#d33f3f}
.banner.hint{background:var(--accent-weak);color:var(--accent-dark);font-weight:var(--w-semibold)}
[data-theme="dark"] .banner.hint{color:#f3915f}


/* 홈 대시보드 */
.card-big .unit{font-size:var(--fs-md);font-weight:var(--w-semibold);color:var(--sub);margin-left:var(--s-1)}
.card.stat.link{cursor:pointer;text-decoration:none;color:inherit;display:block}
.quicklinks{display:flex;flex-wrap:wrap;gap:10px;margin-top:var(--s-9)}
.ql{display:inline-flex;align-items:center;gap:7px;background:var(--card);border:1px solid var(--border);border-radius:var(--r-lg);padding:var(--s-5) var(--s-8);font-size:var(--fs-base);font-weight:var(--w-semibold);transition:var(--d-1) var(--ease)}
.ql:hover{border-color:var(--accent);color:var(--accent-t);transform:translateY(-1px)}
.ql svg{width:16px;height:16px}


/* 세그먼트 탭 */
.seg-tabs{display:inline-flex;gap:4px;background:var(--bg);border:1px solid var(--border);border-radius:var(--r-lg);padding:var(--s-2);margin:var(--s-9) 0 var(--s-7)}
.seg{border:0;background:none;padding:var(--s-4) var(--s-8);border-radius:var(--r-sm);font-size:var(--fs-base);font-weight:var(--w-bold);color:var(--sub);cursor:pointer;font-family:inherit;transition:var(--d-1) var(--ease)}
.seg:hover{color:var(--text)}
.seg.on{background:var(--card);color:var(--accent-t);box-shadow:var(--shadow)}
/* 라디오를 감싼 seg(정기점검 장비 점검결과) — 클릭해도 아무 변화가 없어 "반응이 없다"는 지적을 받았다
   (2026-08-24). 라디오는 display:none 이고 .on 을 붙여줄 JS 가 없었다 → 선택 상태를 CSS 로 직접 그린다.
   이상은 색을 달리해 표에서 바로 눈에 띄게. */
.seg:has(input[type=radio]:checked){background:var(--card);color:var(--accent-t);box-shadow:var(--shadow)}
.seg:has(input[type=radio][value="이상"]:checked){color:var(--err-t)}
.seg:has(input[type=radio][value=""]:checked){color:var(--sub);box-shadow:none}


/* 편집 폼 */
.sel{padding:var(--s-5) var(--s-16) var(--s-5) var(--s-6);border:1px solid var(--border);border-radius:var(--r-md);background:var(--card);color:var(--text);font-family:inherit;font-size:var(--fs-base);font-weight:var(--w-semibold);cursor:pointer;
  -webkit-appearance:none;appearance:none;line-height:1.3;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23999' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 11px center}
/* 프로필 히어로 (마이페이지) */
.prof-hero{display:flex;align-items:center;gap:17px;padding:var(--s-12) var(--s-12);position:relative;overflow:hidden}
.prof-hero::before{content:"";position:absolute;inset:0 0 auto 0;height:3px;background:linear-gradient(90deg,var(--accent),#f7955e)}
.prof-hero .prof-name{margin:0;font-size:var(--fs-xl);font-weight:var(--w-black);letter-spacing:-.02em}
.prof-hero .prof-sub{color:var(--sub);font-size:var(--fs-base);margin-top:var(--s-2)}
.prof-hero .prof-chips{display:flex;gap:6px;flex-wrap:wrap;margin-top:var(--s-5)}
/* minmax(0,…) — 1fr 의 최소폭은 «내용 폭»이라 칸 안 넓은 표(.table-wrap 안이어도)가 칸째 밀어냈다
   (2026-09-25 /manage/ai 모바일 카드 560px). 칸이 줄면 표는 .table-wrap 안에서 스크롤. */
.fgrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}
.field{display:flex;flex-direction:column;gap:6px}
.field>span{font-size:var(--fs-sm);font-weight:var(--w-bold);color:var(--sub)}
.field>div{font-size:var(--fs-md);color:var(--text)}  /* 읽기전용 값 — input(14px)과 동일 크기로 통일 */
.field input,.field textarea,.field select{padding:var(--s-5) var(--s-6);border:1px solid var(--border);border-radius:var(--r-md);background:var(--card);color:var(--text);font-family:inherit;font-size:var(--fs-md);width:100%}
.field input:focus,.field textarea:focus{outline:2px solid var(--accent);border-color:transparent}
/* 체크박스·라디오 = 온길 오렌지(네이티브 파란색 대신 전 앱 통일) */
input[type=checkbox],input[type=radio]{accent-color:var(--accent);cursor:pointer}
.field input[type=checkbox],.field input[type=radio]{width:auto;padding:0;border:0}  /* .field 안이라도 텍스트인풋 스타일 배제 */

/* 커스텀 드롭다운(gwSelects) — 네이티브 select.sel을 진행형 향상. 열린 목록까지 디자인 통일 */
.cs-wrap{position:relative}
.cs-btn{width:100%;display:flex;align-items:center;text-align:left}
.cs-btn .cs-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cs-btn.cs-open{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-weak)}
.cs-panel{position:absolute;left:0;right:0;top:calc(100% + 5px);z-index:60;background:var(--card);border:1px solid var(--border);border-radius:var(--r-md);box-shadow:0 10px 30px rgba(0,0,0,.16);padding:var(--s-3);max-height:280px;overflow-y:auto;animation:gwFade var(--d-1) ease}
.cs-opt{padding:var(--s-5) var(--s-6);border-radius:var(--r-sm);font-size:var(--fs-md);cursor:pointer;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cs-opt:hover{background:color-mix(in srgb,var(--accent) 8%,transparent)}
.cs-opt.on{background:color-mix(in srgb,var(--accent) 12%,transparent);color:var(--accent-t);font-weight:var(--w-bold)}

/* 우측 슬라이드 드로어 — 스플릿(딤 없이 콘텐츠를 왼쪽으로 밀고 우측에 붙음). 항상 DOM, .open 토글 */
:root{--drawer-w:460px}
.drawer-bg{position:fixed;inset:0;z-index:110;background:transparent;pointer-events:none}  /* 딤 없음·좌측 클릭 통과(스플릿) */
.drawer{position:absolute;top:0;right:0;height:100%;width:var(--drawer-w);pointer-events:auto;background:var(--card);
  border-left:1px solid var(--border);box-shadow:-14px 0 40px rgba(0,0,0,.13);
  display:flex;flex-direction:column;transform:translateX(100%);transition:transform var(--d-3) var(--spring,var(--ease))}
.drawer-bg.open .drawer{transform:none}
.drawer-head{display:flex;align-items:center;justify-content:space-between;padding:var(--s-8) var(--s-9);border-bottom:1px solid var(--border);flex-shrink:0}
.drawer-title{font-size:var(--fs-md);font-weight:var(--w-black)}
.drawer-body{flex:1;overflow-y:auto;padding:var(--s-9) var(--s-9) calc(var(--s-9) + env(safe-area-inset-bottom))}
/* 콘텐츠 밀기(스플릿) — 드로어 열리면 #main이 좁아지며 왼쪽으로 (margin=padding 숏핸드와 충돌 회피) */
.main{transition:margin-right var(--d-3) var(--spring,var(--ease))}
body.gw-drawer-push .main{margin-right:var(--drawer-w)}
.seg.seg-mg{color:var(--sub)}
.seg.seg-mg.on{color:var(--accent-t)}
/* 좁은 화면(≤1024px)=스플릿 대신 딤 오버레이로 폴백(콘텐츠 안 밀고 덮음) */
@media (max-width:1024px){
  .drawer-bg{background:rgba(16,20,28,.44);backdrop-filter:blur(2px);opacity:0;pointer-events:none;transition:opacity var(--d-2) var(--ease)}
  .drawer-bg.open{opacity:1;pointer-events:auto}
  .drawer{width:min(560px,94vw)}
  body.gw-drawer-push .main{margin-right:0}
}
@media (max-width:640px){ .drawer{width:100vw;border-left:0} }
@media(max-width:640px){.fgrid{grid-template-columns:minmax(0,1fr)}}
/* 항목·값 표(직원 상세 기본정보 등) — 모바일 공용 규칙이 td 를 nowrap 으로 묶어 이메일·Slack ID 가 표를 520px 로 밀었다(9/25). 값은 줄바꿈. */
.kv-table{min-width:0!important;width:100%}
.kv-table td{white-space:normal!important;overflow-wrap:anywhere}

.qin{padding:var(--s-4) var(--s-5);border:1px solid var(--border);border-radius:var(--r-sm);background:var(--card);color:var(--text);font-family:inherit;font-size:var(--fs-md);width:100%}
.qin:focus{outline:2px solid var(--accent);border-color:transparent}


/* ===== 모바일 하단 탭바 + 반응형 (768px 이하) ===== */
.tabbar{display:none}
[x-cloak]{display:none!important}
@media(max-width:768px){
  /* 🚨 hidden 이 아니라 clip (2026-09-24) — overflow-x:hidden 은 body 를 «스크롤 영역»으로 만들어
     앱바의 position:sticky 가 창이 아니라 body 에 붙는다 → 모바일에서 앱바가 스크롤에 밀려 올라갔다
     (7/3 부터 두 달 반). clip 은 똑같이 자르되 스크롤 영역을 만들지 않는다. hidden 은 구형(iOS<16) 폴백. */
  html,body{max-width:100vw;overflow-x:hidden;overflow-x:clip}
  .sidebar{display:none}
  .content{margin-left:0;padding-bottom:calc(var(--s-32) + env(safe-area-inset-bottom))}
  .appbar{padding:0 var(--s-8);height:52px}
  .user-chip{display:none}
  .main{padding:var(--s-8) var(--s-7) var(--s-12)}
  .page{padding:0}
  .page-title{font-size:var(--fs-xl)}
  /* 🚨 제목 밑에 버튼이 **왼쪽에 고아로** 떨어져 있었다(2026-09-21 실기기 확인).
     앱은 주 동작을 제목과 **같은 줄 오른쪽**에 둔다 — 그 한 줄이 곧 «상단 바»로 읽힌다.
     세로로 세우면 버튼이 본문 블록처럼 보여서, 누를 것인지 읽을 것인지가 흐려진다.
     전수조사(67개): 버튼 없음 45 · 1개 18 · 2개 이상 4(그중 상세 2곳은 ts-head/dt-head 가
     뒤에서 이긴다). 데스크톱 기본이 이미 row + space-between 이라 **세로 지정만 걷어낸다.**
     ⚠️ wrap 은 남긴다 — 제목이 길어 한 줄에 안 들어가면 **오늘과 같은 모습으로** 내려앉을
        뿐이라 최악이 현행이다. min-width:0 은 긴 제목이 버튼을 밀어내지 않게 한다. */
  .page-head{flex-wrap:wrap;gap:var(--s-3) var(--s-5)}
  .page-head > :first-child{flex:1 1 auto;min-width:0}
  .page-head > .btn{flex:0 0 auto}
  .grid{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:10px}
  .card.stat .card-big{font-size:var(--fs-xl)}
  .toolbar{flex-wrap:wrap;gap:8px}
  .search{width:100%}
  .table-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;border-radius:var(--r-lg)}
  .table{min-width:560px}
  .table th,.table td{padding:var(--s-5) var(--s-5);font-size:var(--fs-base);white-space:nowrap}
  .btn{padding:var(--s-6) var(--s-9)}
  .fgrid{grid-template-columns:minmax(0,1fr)}
  .seg-tabs{width:100%;overflow-x:auto;flex-wrap:nowrap;-webkit-overflow-scrolling:touch}
  .seg-tabs::-webkit-scrollbar{display:none}
  .seg{white-space:nowrap;flex-shrink:0}
  /* 하단 탭바 */
  .tabbar{position:fixed;left:0;right:0;bottom:0;z-index:60;display:flex;
    background:var(--card);border-top:1px solid var(--border);
    padding-bottom:env(safe-area-inset-bottom);box-shadow:0 -4px 16px rgba(0,0,0,.06)}
  .tabbar .tab{flex:1;display:flex;flex-direction:column;align-items:center;gap:3px;
    padding:var(--s-5) 0 var(--s-4);font-size:var(--fs-micro);font-weight:var(--w-bold);color:var(--sub);text-decoration:none;
    background:none;border:0;font-family:inherit;cursor:pointer}
  .tabbar .tab svg{width:21px;height:21px;stroke-width:2}
  .tabbar .tab.on{color:var(--accent-t)}
}
/* 전체 시트 (모바일 메뉴) */
.sheet-bg{position:fixed;inset:0;background:rgba(0,0,0,.42);z-index:80;display:flex;align-items:flex-end}
.sheet{background:var(--card);width:100%;border-radius:var(--r-xl) var(--r-xl) 0 0;padding:var(--s-5) var(--s-9) calc(var(--s-10) + env(safe-area-inset-bottom));max-height:72vh;overflow-y:auto;position:relative}
.sheet-grab{width:44px;height:5px;border-radius:var(--r-xs);background:var(--border);margin:var(--s-4) auto var(--s-7);cursor:pointer;position:relative}
.sheet-grab::before{content:"";position:absolute;inset:-14px -60px;/* 히트영역 확대 */}
.sheet-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;margin-bottom:var(--s-6)}
.sheet-grphd{font-size:var(--fs-sm);font-weight:var(--w-bold);color:var(--sub);margin:var(--s-4) var(--s-2) var(--s-3)}
.sheet-item{display:flex;flex-direction:column;align-items:center;gap:6px;padding:var(--s-7) var(--s-2);
  border-radius:var(--r-lg);font-size:var(--fs-sm);font-weight:var(--w-bold);color:var(--text);text-decoration:none}
.sheet-item svg{width:22px;height:22px;stroke-width:1.8;color:var(--sub)}
.sheet-item.on{background:color-mix(in srgb, var(--accent) 9%, transparent);color:var(--accent-t)}
.sheet-item.on svg{color:var(--accent-t)}
.sheet-item:active{background:var(--bg)}
@keyframes sheetup{from{transform:translateY(24px);opacity:.6}to{transform:none;opacity:1}}
.sheet{animation:sheetup var(--d-3) var(--spring)}

/* 모바일 폴리시 2차 */
@media(max-width:768px){
  /* 출퇴근 버튼 = 엄지 타깃 풀와이드 */
  .today-actions{width:100%}
  .today-actions form{width:100%}
  .today-actions .btn{width:100%;padding:var(--s-8) 0!important;font-size:var(--fs-lg)!important;border-radius:var(--r-lg)}
  /* 인라인 폼 필드 = 세로 스택 풀와이드 */
  form .field{max-width:100%!important;width:100%}
  form .sel{width:100%}
  /* 폼 제출 버튼 크게 */
  .card form>.btn, .card form button[type=submit]{padding:var(--s-7) var(--s-12)}
  /* 표 — 폰트는 본문(13.5px)과 통일, 밀도는 패딩으로 */
  .table th,.table td{font-size:var(--fs-base);padding:var(--s-5) var(--s-5)}
  .table{min-width:520px}
  /* 배너/카드 여백 */
  .card{border-radius:var(--r-lg)}
  .banner{font-size:var(--fs-base)}
  /* 시트 아이템 터치 피드백 */
  .sheet-item{padding:var(--s-8) var(--s-2)}
  /* 홈 등 페이지 헤더 버튼 랩 */
  .page-head .btn{padding:var(--s-5) var(--s-7);font-size:var(--fs-base)}
}

/* 근무 상태 버튼 */
.stb{display:inline-flex;align-items:center;gap:7px;padding:var(--s-5) var(--s-8);border:1px solid var(--border);border-radius:var(--r-md);background:var(--bg);color:var(--text);font-family:inherit;font-size:var(--fs-base);font-weight:var(--w-semibold);cursor:pointer;transition:var(--d-2) var(--ease)}
.stb:hover{border-color:color-mix(in srgb, var(--accent) 45%, var(--border));transform:translateY(-1px)}
.stb.on{border-color:var(--accent-dark);background:var(--accent-dark);color:#fff;font-weight:var(--w-bold);box-shadow:0 4px 12px rgba(232,100,42,.3)}
.stb.on .dot{background:#fff!important}
.dot.accent{background:var(--accent)}
@media(max-width:768px){.stb{padding:var(--s-6) var(--s-8);font-size:var(--fs-base)}}

/* 온길 비서 */
.assistant-fab{position:fixed;right:22px;bottom:22px;z-index:70;width:52px;height:52px;border-radius:50%;
  border:0;background:var(--accent);color:#fff;cursor:pointer;box-shadow:0 6px 20px rgba(232,100,42,.35);
  display:flex;align-items:center;justify-content:center;transition:var(--d-2) var(--ease)}
.assistant-fab:hover{transform:scale(1.06)}
.assistant-fab svg{width:23px;height:23px}
.assistant-panel{position:fixed;right:22px;bottom:84px;z-index:75;width:min(360px,calc(100vw - 28px));
  background:var(--card);border:1px solid var(--border);border-radius:var(--r-xl);box-shadow:0 16px 48px rgba(0,0,0,.18);
  display:flex;flex-direction:column;height:min(520px,70vh);height:min(520px,70dvh)}
.assistant-head{display:flex;align-items:center;padding:var(--s-7) var(--s-8);font-weight:var(--w-black);font-size:var(--fs-md);border-bottom:1px solid var(--border)}
.assistant-body{flex:1;overflow-y:auto;padding:var(--s-7) var(--s-8);display:flex;flex-direction:column;gap:8px}
.as-me{align-self:flex-end;background:var(--accent);color:#fff;padding:var(--s-5) var(--s-7);border-radius:var(--r-lg) var(--r-lg) var(--r-xs) var(--r-lg);font-size:var(--fs-base);max-width:85%;white-space:pre-line}
.as-bot{align-self:flex-start;background:var(--bg);padding:var(--s-5) var(--s-7);border-radius:var(--r-lg) var(--r-lg) var(--r-lg) var(--r-xs);font-size:var(--fs-base);max-width:90%;white-space:pre-line;line-height:1.6}
.assistant-input{display:flex;gap:8px;padding:var(--s-6);border-top:1px solid var(--border)}
.assistant-input input{flex:1;min-width:0;padding:var(--s-5) var(--s-7);border:1px solid var(--border);border-radius:var(--r-md);background:var(--bg);color:var(--text);font-family:inherit;font-size:var(--fs-md)}
.assistant-input button{flex:none;white-space:nowrap}
@media(max-width:768px){.assistant-fab{bottom:calc(var(--s-32) + env(safe-area-inset-bottom));right:16px}
  .assistant-panel{bottom:calc(var(--s-32) + env(safe-area-inset-bottom));right:14px;left:14px;width:auto;height:58vh;height:min(58dvh,480px)}}

/* 테이블 정렬/필터 */
th.sortable{cursor:pointer;user-select:none;position:relative}
th.sortable:hover{color:var(--accent-t)}
th.s-a::after{content:" ↑";color:var(--accent-t);font-size:var(--fs-xs)}
th.s-d::after{content:" ↓";color:var(--accent-t);font-size:var(--fs-xs)}
.tfilter th{padding:var(--s-2) var(--s-4) var(--s-4);background:var(--card)}
.tfilter input{width:100%;box-sizing:border-box;padding:var(--s-3) var(--s-4);border:1px solid var(--border);border-radius:var(--r-sm);background:var(--bg);color:var(--text);font-family:inherit;font-size:var(--fs-sm)}
.tfilter input:focus{outline:1.5px solid var(--accent);border-color:transparent}
.tfilter input::placeholder{color:color-mix(in srgb, var(--sub) 55%, transparent)}
@media(max-width:768px){.tfilter{display:none}}

/* 테이블 엔진 v2 */
.tbl-tools{display:flex;justify-content:flex-end;align-items:center;gap:10px;padding:var(--s-7) var(--s-8) var(--s-6);margin:0}
.tbl-csv{border:1px solid var(--border);background:var(--card);color:var(--sub);border-radius:var(--r-sm);padding:var(--s-3) var(--s-6);font-size:var(--fs-sm);font-weight:var(--w-bold);cursor:pointer;font-family:inherit}
.tbl-csv:hover{color:var(--accent-t);border-color:var(--accent)}
.tbl-search{border:1px solid var(--border);background:var(--bg);color:var(--text);border-radius:var(--r-sm);padding:var(--s-3) var(--s-6);font-size:var(--fs-sm);font-family:inherit;width:200px;margin-right:auto;transition:border-color var(--d-1) var(--ease),box-shadow var(--d-1) var(--ease)}
@media(max-width:768px){.tbl-search{width:100%;margin-right:0}}
.tbl-search:focus{outline:0;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-weak)}
@media(max-width:768px){.tbl-search{width:auto;flex:1 1 140px;min-width:0;font-size:var(--fs-base)!important}}
/* 🚨 flex-basis 140px + 줄바꿈(2026-09-24) — basis 가 0 이면 칩이 자리를 먹는 만큼 검색칸이 **끝없이** 눌렸다
   (폰 390px 실측: 프로젝트·재고·세일즈 26px · 견적 65px — 안내문도 안 보이고 누르기도 어려웠다).
   140px 가 안 남으면 검색칸이 다음 줄로 내려가 한 줄을 다 쓴다. 줄이 나뉘면 오른쪽 정렬이 칩을 쏠리게 해서 왼쪽으로. */
@media(max-width:768px){.tbl-tools{flex-wrap:wrap;justify-content:flex-start}}  /* 표 텍스트와 통일(16px 강제 제외) — iOS 탭 시 소폭 확대 감수 */
th.sortable{cursor:pointer}
.col-rz{position:absolute;right:0;top:0;bottom:0;width:7px;cursor:col-resize}
.col-rz:hover{background:color-mix(in srgb, var(--accent) 30%, transparent)}
th.col-over{background:color-mix(in srgb, var(--accent) 10%, transparent)}
@media(max-width:768px){.tbl-tools{display:none}.col-rz{display:none}}

/* 상태 칩 필터 */
.tbl-tools{align-items:center;gap:10px}
.chips{display:flex;gap:6px;flex-wrap:wrap;margin-right:auto}
.chip{border:1px solid var(--border);background:var(--card);color:var(--sub);border-radius:var(--r-xl);padding:var(--s-3) var(--s-6);font-size:var(--fs-sm);font-weight:var(--w-bold);cursor:pointer;font-family:inherit;transition:var(--d-1) var(--ease)}
.chip:hover{color:var(--text)}
.chip.on{background:color-mix(in srgb, var(--accent) 10%, transparent);border-color:var(--accent);color:var(--accent-t)}
@media(max-width:768px){.tbl-tools{display:flex}.chips{margin:0}.tbl-csv{display:none}}

/* 엔진 v3: 컬럼 메뉴·밀도·숨김 */
.tbl-right{display:flex;gap:6px;align-items:center;flex-shrink:0}
.tbl-csv{white-space:nowrap;flex-shrink:0}  /* 9/27: 재고 도구줄에서 «잠금 해제(셀 편집)»·«컬럼»이 눌려 두 줄·세로로 쪼개졌다 */
.colmenu-wrap{position:relative}
.colmenu{position:absolute;right:0;top:calc(100% + 6px);z-index:40;background:var(--card);border:1px solid var(--border);border-radius:var(--r-lg);box-shadow:var(--shadow);padding:var(--s-5) var(--s-7);display:flex;flex-direction:column;gap:7px;min-width:150px;max-height:300px;overflow-y:auto}
.colmenu label{display:flex;align-items:center;gap:8px;font-size:var(--fs-base);cursor:pointer;white-space:nowrap}
.col-hide{display:none!important}
.t-dense th,.t-dense td{padding:var(--s-3) var(--s-5)!important;font-size:var(--fs-sm)!important}

.colmenu[hidden]{display:none!important}

/* ===== 기존 그룹웨어 디자인 정렬: 와이드 사이드바 + 그룹 + 홈 위젯 ===== */
.sidebar{width:212px;align-items:stretch}
.sbrand{flex-direction:row;align-items:center;gap:10px;padding:var(--s-8) var(--s-8) var(--s-7);justify-content:flex-start}
.sbrand .logo{width:30px;height:30px;border-radius:var(--r-sm)}
.sbrand-txt{display:flex;flex-direction:column;line-height:1.25}
.sbrand-txt b{font-size:var(--fs-md);color:var(--sb-brand)}
.sbrand-txt small{font-size:var(--fs-micro);color:var(--sb-brand-sub);font-weight:var(--w-semibold)}
.sbrand + .navwrap{padding-top:var(--s-1)}
.navwrap{padding:0 var(--s-5) var(--s-8)}
.navgroup{font-size:var(--fs-micro);font-weight:var(--w-black);letter-spacing:.06em;color:var(--sb-group);padding:var(--s-8) var(--s-4) var(--s-3)}
.navi{flex-direction:row;justify-content:flex-start;gap:10px;padding:var(--s-4) var(--s-5);border-radius:var(--r-sm);margin:var(--s-hair) 0;font-size:var(--fs-base);font-weight:var(--w-semibold);color:var(--sb-text)}
.navi svg,.navi i[data-lucide]{width:17px;height:17px;flex-shrink:0;display:block}
.navi span{font-size:var(--fs-base)}
.navi:hover{background:var(--sb-hover-bg);color:var(--sb-text-hover)}
.navi.on{background:var(--accent-weak);color:var(--accent-dark)}
.navi.on svg{color:var(--accent-t)}
.content{margin-left:var(--nav-w)}
@media(max-width:768px){.content{margin-left:0}}

/* 홈 위젯 그리드 (기존 레이아웃) */
.wgrid{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:14px}
/* 드래그 커서는 편집모드에서만 — .wg-edit [data-wg] 참조. 2026-09-21: 상시 grab 은
   편집모드 밖에서도 끌 수 있던 옛 구현의 잔재였고, 그 드래그는 저장돼도 되돌아갔다. */
.wg-ghost{opacity:.35;outline:2px dashed var(--accent);outline-offset:2px}
.wev-d{font-size:var(--fs-sm);color:var(--sub);min-width:64px}
.wev-d.on{color:var(--accent-t);font-weight:var(--w-black)}
.wev-past{opacity:.5}
.widget{padding:var(--s-9) var(--s-9);grid-column:span 2;min-width:0;display:flex;flex-direction:column;gap:7px}
.widget.w2{grid-column:span 3}
/* 위젯 헤더 = 아이콘 칩 + 제목 (공용 스탯카드 컴포넌트) */
.wtitle{font-size:var(--fs-base);font-weight:var(--w-bold);color:var(--text);letter-spacing:-.01em;display:flex;align-items:center;gap:10px;margin-bottom:var(--s-hair)}
.wg-ic{width:34px;height:34px;flex:none;border-radius:var(--r-md);display:grid;place-items:center;background:var(--accent-weak);color:var(--accent-t)}
.wg-ic svg{width:18px;height:18px;stroke-width:1.9}
.wg-ic.v{background:rgba(139,92,246,.14);color:#8B5CF6}
.wg-ic.b{background:rgba(59,130,246,.14);color:#3B82F6}
.wg-ic.g{background:rgba(16,185,129,.14);color:var(--ok-t)}
.wg-ic.w{background:rgba(245,158,11,.15);color:var(--warn-t)}
.wg-ic.r{background:rgba(239,68,68,.14);color:var(--err-t)}
.wg-ic.m{background:color-mix(in srgb,var(--border) 45%,transparent);color:var(--sub)}
/* 아이콘 스탯카드 (공용) — 홈 위젯과 동일 아이콘 칩을 KPI 카드에 */
.card.stat.has-ic{display:flex;align-items:center;gap:13px}
.card.stat.has-ic .stat-body{display:flex;flex-direction:column;min-width:0}
.card.stat.has-ic .card-label{margin-bottom:var(--s-1)}
/* 월근로 — 진행률/예상 프로그레스 */
.wtp{display:flex;flex-direction:column;gap:6px;width:100%;min-width:150px;padding:var(--s-2) 0}
.wtp-bar{position:relative;height:8px;width:100%;background:var(--border);border-radius:var(--r-xs);overflow:hidden;display:block}
.wtp-fill{height:100%;min-width:3px;background:var(--accent);border-radius:var(--r-xs);transition:width var(--d-3) var(--ease)}
.wtp-fill.over{background:var(--err)}
.wtp-txt{font-size:var(--fs-xs);color:var(--sub);line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.wtp-txt b{color:var(--text);font-weight:var(--w-bold);font-variant-numeric:tabular-nums}
.wtp-o{color:var(--err-t);font-weight:var(--w-bold)}
.wtp-o b{color:var(--err-t)}
/* 근무 감사 — 주간 동시 진행 스트립 (요일별 스트림 수, 강도 색) */
.conc-strip{display:flex;flex-wrap:wrap;gap:3px;max-width:240px}
.conc-strip.compact{gap:3px;max-width:392px}
.conc{width:22px;height:22px;flex:none;border-radius:var(--r-xs);display:grid;place-items:center;font-size:var(--fs-xs);
  font-weight:var(--w-bold);background:var(--hair);color:var(--sub);font-variant-numeric:tabular-nums}
.conc-strip.compact .conc{width:13px;height:13px;border-radius:var(--r-xs);font-size:0}
.conc[data-n="1"]{background:rgba(232,100,42,.13);color:var(--accent-t)}
.conc[data-n="2"]{background:rgba(232,100,42,.24);color:var(--accent-t)}
.conc[data-n="3"]{background:rgba(232,100,42,.42);color:#fff}
.conc[data-n="4"],.conc[data-n="5"],.conc[data-n="6"],.conc[data-n="7"],.conc[data-n="8"],.conc[data-n="9"]{background:var(--accent);color:#fff}
/* 근무 감사 — 직원 드릴다운(참여 건 상세) */
.dd{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:10px;padding:var(--s-6) var(--s-7);background:var(--bg)}
.dd-cat{background:var(--card);border:1px solid var(--border);border-radius:var(--r-md);padding:var(--s-5) var(--s-6)}
.dd-h{font-size:var(--fs-sm);font-weight:var(--w-bold);margin-bottom:var(--s-3)}
.dd-i{display:flex;justify-content:space-between;gap:8px;padding:var(--s-2) 0;font-size:var(--fs-sm);border-top:1px solid var(--hair)}
.dd-i:first-of-type{border-top:0}
.dd-l{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--sub)}
.dd-w{flex:none;font-variant-numeric:tabular-nums;font-weight:var(--w-semibold);color:var(--sub)}
[x-cloak]{display:none!important}
/* Tabulator 빈 상태 placeholder (공용) */
.tbl-empty{display:flex;flex-direction:column;align-items:center;gap:9px;padding:var(--s-14) 0;color:var(--sub);font-size:var(--fs-base)}
.tbl-empty svg{width:30px;height:30px;opacity:.45;stroke-width:1.7}
.wtitle .wt-x{margin-left:auto;font-weight:var(--w-medium);font-size:var(--fs-xs);color:var(--sub)}
.wbig{font-size:var(--fs-2xl);font-weight:var(--w-black);letter-spacing:-.02em;font-variant-numeric:tabular-nums;line-height:1.12}
.wbig .unit{font-size:var(--fs-md);font-weight:var(--w-bold);color:var(--sub);margin-left:var(--s-1)}
.wrow{display:flex;align-items:center;gap:10px;padding:var(--s-4) 0;border-bottom:1px solid color-mix(in srgb, var(--border) 55%, transparent);font-size:var(--fs-base)}
.wrow:last-of-type{border-bottom:none}
.wmain{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:var(--w-semibold)}
.wmain b{font-weight:var(--w-bold)}
.wempty{display:flex;flex-direction:column;align-items:center;gap:8px;padding:var(--s-9) 0 var(--s-4);color:var(--sub);text-align:center;font-size:var(--fs-sm)}
.wempty svg{width:26px;height:26px;opacity:.45;stroke-width:1.7}
.wlink{margin-top:auto;padding-top:var(--s-4);font-size:var(--fs-sm);font-weight:var(--w-semibold);color:var(--sub);text-decoration:none;
  display:inline-flex;align-items:center;gap:4px;width:fit-content;transition:color var(--d-1) var(--ease)}
.wlink:hover{color:var(--accent-t)}
.wlink svg{width:14px;height:14px}
/* 상태 칩 (공용) — 색으로 상태를 인코딩 */
.wchip{flex:none;font-size:var(--fs-micro);font-weight:var(--w-bold);padding:var(--s-2) var(--s-5);border-radius:var(--r-pill);letter-spacing:.01em;
  background:var(--hair,color-mix(in srgb,var(--border) 45%,transparent));color:var(--sub)}
.wchip.prog{background:rgba(59,130,246,.13);color:var(--st-blue)}
.wchip.ok{background:rgba(16,185,129,.14);color:var(--ok-t)}
.wchip.warn{background:rgba(245,158,11,.15);color:var(--warn-t)}
.wchip.accent{background:var(--accent-weak);color:var(--accent-t)}
.wchip.err{background:rgba(239,68,68,.14);color:var(--err-t)}
.wchip.wait{background:color-mix(in srgb,var(--border) 45%,transparent);color:var(--sub)}
/* 근태 동선 타임라인 (공용) */
.att-timeline{margin-top:var(--s-7);padding-top:var(--s-6);border-top:1px dashed var(--border);display:flex;align-items:center;
  gap:8px;flex-wrap:wrap;color:var(--sub);font-size:var(--fs-sm);line-height:1.7}
.att-timeline b{color:var(--text);font-weight:var(--w-bold);font-variant-numeric:tabular-nums}
.att-timeline .arr{color:var(--border);font-weight:var(--w-bold)}
/* 시간축 동선 바(간트식) — 홈 위젯·근태탭·관리자 일별 보드 공용 */
.att-tl-wrap .tl-axis{position:relative;height:12px;margin-bottom:var(--s-2)}
.att-tl-wrap .tl-t{position:absolute;font-size:var(--fs-micro);font-weight:var(--w-semibold);color:var(--sub);transform:translateX(-50%);font-variant-numeric:tabular-nums}
.att-bar.tl{position:relative;display:block;height:18px;border-radius:var(--r-xs);overflow:visible;background:var(--bg)}
.att-bar.tl .tl-grid{position:absolute;top:-2px;bottom:-2px;width:0;border-left:1px dotted var(--border);z-index:0}
.att-bar.tl .sg{position:absolute;top:0;height:100%;min-width:2px;z-index:1}
.att-bar.tl .sg:first-of-type,.att-bar.tl .tl-grid + .sg{border-radius:var(--r-xs) 0 0 var(--r-xs)}   /* 첫 세그먼트 왼쪽 라운드 — .sg 앞에 tl-grid span들이 있어 :first-of-type만으론 안 잡힘 → grid 뒤 첫 .sg */
.att-bar.tl .sg:last-of-type{border-radius:0 var(--r-xs) var(--r-xs) 0}
.att-bar.tl .sg:first-of-type:last-of-type,.att-bar.tl .tl-grid + .sg:last-of-type{border-radius:var(--r-xs)}   /* 세그먼트 하나면 4모서리 */
.att-bar.tl .sg.field{background:var(--accent)}
.att-bar.tl .sg.disp{background:#14B8A6}
.att-bar.tl .sg.office{background:var(--ok)}
.att-bar.tl .sg.home{background:#8B5CF6}
.sg.home{background:#8B5CF6}  /* 재택(원격) — 전 바 공통 폴백, 버튼 점 색과 동일 */
.att-bar.tl .sg.move{background:#3B82F6}
.att-bar.tl .sg.brk{background:var(--sub)}
.att-bar.tl .sg.commute{background:repeating-linear-gradient(45deg,#94A3B8,#94A3B8 3px,#CBD5E1 3px,#CBD5E1 6px)}
/* 히어로 현재상태 pill */
.statuspill{display:inline-flex;align-items:center;gap:6px;padding:var(--s-2) var(--s-6);border-radius:var(--r-pill);
  background:var(--accent-weak);color:var(--accent-t);font-weight:var(--w-bold);font-size:var(--fs-sm);vertical-align:middle}
.statuspill .sd{width:6px;height:6px;border-radius:50%;background:currentColor}
@media(max-width:1100px){.wgrid{grid-template-columns:repeat(2,minmax(0,1fr))}.widget,.widget.w2{grid-column:span 1}}
@media(max-width:768px){.wgrid{grid-template-columns:minmax(0,1fr)}.widget,.widget.w2{grid-column:span 1}}

/* 홈 위젯 편집 모드 */
.wg-edit [data-wg]{cursor:grab;outline:1.5px dashed color-mix(in srgb, var(--accent) 45%, transparent);outline-offset:3px;position:relative}
.wg-edit [data-wg]:active{cursor:grabbing}
.wg-x{position:absolute;top:8px;right:8px;width:22px;height:22px;border-radius:50%;border:0;background:var(--err,#EF4444);color:#fff;font-size:var(--fs-xs);cursor:pointer;line-height:1}
.wg-sz{position:absolute;top:8px;right:36px;border:1px solid var(--border);background:var(--card);color:var(--sub);border-radius:var(--r-sm);padding:var(--s-2) var(--s-4);font-size:var(--fs-xs);font-weight:var(--w-bold);cursor:pointer;font-family:inherit}
.sortable-ghost{opacity:.4}

/* 비서 배지·평가·알림 */
.fab-badge{position:absolute;top:-3px;right:-3px;min-width:19px;height:19px;border-radius:var(--r-md);background:#DC2626;color:#fff;font-size:var(--fs-xs);font-weight:var(--w-black);display:flex;align-items:center;justify-content:center;padding:0 var(--s-3)}
.assistant-fab{position:fixed}
.as-tabs{display:flex;gap:2px;background:var(--bg);border-radius:var(--r-md);padding:var(--s-2);margin:var(--s-5) var(--s-7) var(--s-2)}
.as-tab{all:unset;flex:1;display:flex;align-items:center;justify-content:center;gap:5px;padding:var(--s-3) 0;border-radius:var(--r-sm);font-size:var(--fs-sm);font-weight:var(--w-semibold);color:var(--sub);cursor:pointer;transition:all var(--d-1)}
.as-tab.on{background:var(--card,#fff);color:var(--text);font-weight:var(--w-black);box-shadow:0 1px 4px rgba(0,0,0,.07);border:1px solid var(--border)}
.as-tab-badge{background:var(--accent);color:#fff;border-radius:var(--r-pill);padding:0 var(--s-3);font-size:var(--fs-micro);line-height:16px;font-weight:var(--w-bold)}
.as-rate{all:unset;cursor:pointer;color:var(--sub);opacity:.5;padding:var(--s-2);border-radius:var(--r-xs);display:inline-flex;transition:all var(--d-1)}
.as-rate:hover{opacity:.9;background:var(--bg)}
.as-rate.on{opacity:1;color:var(--ok-t,#16a34a)}
.as-rate.dn.on{color:#EF4444}
.as-dismiss{all:unset;cursor:pointer;color:var(--sub);opacity:.45;padding:var(--s-2);border-radius:var(--r-xs);display:inline-flex}
.as-dismiss:hover{opacity:.9;background:var(--bg)}
.as-typing{display:inline-flex;gap:5px;align-items:center;padding:var(--s-7) var(--s-8);min-height:0}
.as-typing span{width:7px;height:7px;border-radius:50%;background:var(--sub);opacity:.4;animation:as-bounce 1.15s infinite ease-in-out}
.as-typing span:nth-child(2){animation-delay:.15s}
.as-typing span:nth-child(3){animation-delay:.3s}
@keyframes as-bounce{0%,60%,100%{transform:translateY(0);opacity:.35}30%{transform:translateY(-4px);opacity:.9}}
.as-notif{background:var(--card,#fff);border:1px solid var(--border);border-radius:var(--r-lg);padding:var(--s-5) var(--s-6);font-size:var(--fs-sm);transition:box-shadow var(--d-1),border-color var(--d-1)}
.as-notif:hover{border-color:color-mix(in srgb, var(--accent) 35%, var(--border));box-shadow:0 2px 10px rgba(0,0,0,.05)}
.as-notif button:hover{color:var(--text)}
.as-news{display:flex;flex-direction:column;gap:var(--s-3)}
.as-news-bar{display:flex;justify-content:flex-end}
.as-news-all{all:unset;cursor:pointer;font-size:var(--fs-xs);color:var(--sub)}
.as-news-all:hover{color:var(--text)}
.as-news-item{display:flex;gap:var(--s-4);align-items:flex-start;text-decoration:none;color:inherit;cursor:pointer}
.as-news-dot{flex:none;width:6px;height:6px;margin-top:var(--s-3);border-radius:var(--r-pill);background:transparent}
.as-news-item.unread .as-news-dot{background:var(--accent)}
.as-news-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:var(--s-1)}
.as-news-head{display:flex;gap:var(--s-4);align-items:baseline}
.as-news-title{flex:1;min-width:0;font-size:var(--fs-sm);color:var(--sub);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.as-news-item.unread .as-news-title{color:var(--text);font-weight:var(--w-bold)}
.as-news-at{flex:none;font-size:var(--fs-micro);color:var(--sub)}
.as-news-body{font-size:var(--fs-xs);color:var(--sub);white-space:pre-line;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.as-news-body.open{display:block}

/* ═══ 깊이·그래픽 레이어 (2026-07-05 — 3D 느낌, 토스 톤 유지·성능 우선) ═══ */
/* 배경 앰비언트 글로우 — 은은한 오렌지/블루 궤도 */
body{background-image:
  radial-gradient(720px 480px at 88% -12%, color-mix(in srgb, var(--accent) 6%, transparent), transparent 68%),
  radial-gradient(820px 560px at -14% 112%, rgba(59,130,246,.045), transparent 70%);
  background-attachment:fixed;background-repeat:no-repeat}
[data-theme="dark"] body{background-image:
  radial-gradient(720px 480px at 88% -12%, rgba(232,100,42,.10), transparent 68%),
  radial-gradient(820px 560px at -14% 112%, rgba(59,130,246,.07), transparent 70%)}

/* 카드 = 유리+상단 하이라이트+깊은 그림자, 호버 시 액센트 글로우 */
.card{box-shadow:var(--shadow), inset 0 1px 0 rgba(255,255,255,.03);
  background-image:linear-gradient(180deg, rgba(255,255,255,.02), transparent 42%)}
[data-theme="light"] .card, :root:not([data-theme="dark"]) .card{background-image:none}
.card.stat:hover, .card.widget:hover{box-shadow:var(--shadow-lift),
  0 0 0 1px color-mix(in srgb, var(--accent) 22%, transparent),
  0 14px 44px color-mix(in srgb, var(--accent) 10%, transparent)}
.card.stat, .card.widget{transform-style:preserve-3d;will-change:transform}

/* KPI 숫자 — 그라디언트 텍스트 (톤 컬러는 유지) */
.card-big:not(.tone-ok):not(.tone-warn):not(.tone-err){
  background:linear-gradient(120deg, var(--text) 30%, color-mix(in srgb, var(--text) 45%, var(--accent)));
  -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}

/* 앱바 글래스 */
.appbar{backdrop-filter:blur(14px) saturate(1.4);-webkit-backdrop-filter:blur(14px) saturate(1.4);
  background:color-mix(in srgb, var(--card) 72%, transparent)!important;
  border-bottom:1px solid color-mix(in srgb, var(--border) 70%, transparent)}

/* 🎬 스크롤 가장자리(2026-09-21) — 맨 위에선 경계가 없고, 내용이 바 밑으로 들어가기
   **시작할 때** 비로소 선이 생긴다. 지금까지는 항상 흰 바 + 테두리라 첫 화면부터
   «떠 있는 띠»로 보였다. 이어져 보이다가 필요할 때만 분리되는 게 앱이다.
   🚨 위 규칙의 background 가 !important 라 여기서도 짝을 맞춰야 뒤집힌다(새로 늘리는 게 아니다). */
.appbar{transition:background var(--d-2) var(--ease),border-color var(--d-2) var(--ease),
  box-shadow var(--d-2) var(--ease)}
html:not(.gw-scrolled) .appbar{background:var(--bg)!important;border-bottom-color:transparent;
  backdrop-filter:none;-webkit-backdrop-filter:none}
html.gw-scrolled .appbar{box-shadow:0 4px 14px color-mix(in srgb, var(--text) 5%, transparent)}

/* 사이드바 활성 (2026-08-25 톤 다운) — 그라디언트 필 + 글로우는 **화면에서 가장 강한 요소**였다.
   지금 어디 있는지 알려주는 표시일 뿐인데, 본문의 경고·강조보다 세면 눈이 거기로 끌린다.
   옅은 면 + 왼쪽 강조선 + 오렌지 글자로 낮춘다(위치는 그대로 또렷하다). */
.navi.on{background:var(--accent-weak)!important;color:var(--accent-dark)!important;
  box-shadow:inset 3px 0 0 var(--accent);font-weight:var(--w-bold)}
.navi.on svg{color:var(--accent-t)!important}
[data-theme="dark"] .navi.on{background:rgba(232,100,42,.14)!important;color:#f3915f!important}

/* 주 버튼 = 그라디언트 + 글로우 */
.btn:not(.ghost){background:linear-gradient(135deg, var(--accent) 20%, #ef7a3f);
  box-shadow:0 4px 14px rgba(232,100,42,.24), inset 0 1px 0 rgba(255,255,255,.24)}
.btn:not(.ghost):hover{background:linear-gradient(135deg, var(--accent-dark) 15%, var(--accent));
  box-shadow:0 6px 20px rgba(232,100,42,.38), inset 0 1px 0 rgba(255,255,255,.2)}

/* 모달·시트 깊이 */
.modal{box-shadow:0 24px 80px rgba(0,0,0,.35), 0 0 0 1px color-mix(in srgb, var(--border) 60%, transparent),
  inset 0 1px 0 rgba(255,255,255,.05)}

/* 접근성: 모션 최소화 환경에선 틸트/글로우 전환 억제 */
@media (prefers-reduced-motion: reduce){
  .card.stat, .card.widget{transform:none!important}
}


/* ── 상단 로딩바 (페이지 이동 피드백) ── */
#np{position:fixed;top:0;left:0;height:3px;width:0;z-index:9999;opacity:0;pointer-events:none;
  background:linear-gradient(90deg,var(--accent),#f0854f 60%,#ffb289);
  box-shadow:0 0 10px color-mix(in srgb, var(--accent) 60%, transparent);
  transition:width var(--d-3) var(--ease),opacity .4s var(--ease)}
#np.on{opacity:1}


/* ── 사이드바 개인화 ── */
.nav-grphd{cursor:pointer;display:flex;align-items:center;gap:5px;user-select:none}
.nav-chev{width:11px;height:11px;opacity:.6;transition:transform var(--d-2)}
.navsec.nav-closed .nav-chev{transform:rotate(-90deg)}
.nav-editbtn{background:none;border:0;width:100%;text-align:left;cursor:pointer;font-family:inherit;font-size:inherit}
.nav-editbtn.on{opacity:1 !important;color:var(--accent-t)}
.nav-ctls{margin-left:auto;display:inline-flex;gap:2px}
.nav-gctls{margin-left:auto;display:inline-flex;gap:2px}
.nav-editing .nav-grphd{cursor:default}
.nav-ctl{background:none;border:0;padding:var(--s-2);cursor:pointer;color:var(--sub);border-radius:var(--r-xs);display:inline-flex}
.nav-ctl:hover{color:var(--accent-t);background:color-mix(in srgb, var(--accent) 12%, transparent)}
body.nav-editing .navi.nav-hidden{opacity:.38}
body.nav-editing .navi{cursor:default}
.navi[data-nav] .nav-ctls .c-star{color:var(--sub)}
#navFavBody .navi .c-star, body.nav-editing #navFavBody .navi{color:inherit}
#navFavBody .navi .nav-ctls .c-star{color:var(--accent-t)}


/* ── 상단 브레드크럼 ── */
.crumbs{display:flex;align-items:center;gap:0;font-size:var(--fs-md);font-weight:var(--w-bold);letter-spacing:-.01em}
.crumbs a{color:var(--sub);text-decoration:none;transition:color var(--d-1) var(--ease)}
.crumbs a:hover{color:var(--accent-t)}
.crumbs .cur{color:var(--text)}
.crumbs span:not(.cur):not(.sep){color:var(--sub)}
.crumbs .sep{color:var(--sub);opacity:.5;margin:0 var(--s-4);font-weight:var(--w-normal)}


/* ── 고객사 목록(아바타 카드/행) ── */
.cs-sec{font-size:var(--fs-sm);font-weight:var(--w-black);color:var(--sub);letter-spacing:.02em;margin:var(--s-8) var(--s-1) var(--s-5);display:flex;align-items:center;gap:6px}
.cs-sec:first-of-type{margin-top:var(--s-3)}
.cs-star-mini{color:var(--accent-t)}
.cs-av{border-radius:var(--r-md);display:flex;align-items:center;justify-content:center;font-weight:var(--w-black);color:#fff;flex-shrink:0;letter-spacing:-.02em}
.cs-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:11px}
.cs-card{position:relative;background:var(--card);border:1px solid var(--border);border-radius:var(--r-xl);padding:var(--s-8) var(--s-7) var(--s-7);text-align:center;transition:border-color var(--d-1) var(--ease),transform var(--d-1) var(--ease),box-shadow var(--d-1) var(--ease)}
.cs-card:hover{border-color:color-mix(in srgb,var(--accent) 45%,var(--border));transform:translateY(-2px);box-shadow:0 8px 22px rgba(0,0,0,.07)}
.cs-card-lnk{display:flex;flex-direction:column;align-items:center;gap:8px;color:inherit;text-decoration:none}
.cs-card .cs-av{margin:0 auto}
.cs-card-nm{font-weight:var(--w-black);font-size:var(--fs-base);letter-spacing:-.02em;line-height:1.3;word-break:keep-all}
.cs-card-meta{font-size:var(--fs-xs);color:var(--sub);line-height:1.4}
.cs-card .cs-star{position:absolute;top:9px;right:10px}
.cs-card .cs-edit{margin-top:var(--s-6);padding:var(--s-2) var(--s-6);font-size:var(--fs-xs)}
.cs-list{display:flex;flex-direction:column;gap:0;border:1px solid var(--border);border-radius:var(--r-lg);overflow:hidden;background:var(--card)}
.cs-row{display:flex;align-items:center;gap:12px;padding:var(--s-6) var(--s-8);color:inherit;text-decoration:none;border-bottom:1px solid var(--border);transition:background var(--d-1) var(--ease)}
.cs-row:last-child{border-bottom:0}
.cs-row:hover{background:var(--bg)}
.cs-row-main{flex:1;min-width:0}
.cs-row-nm{font-weight:var(--w-bold);font-size:var(--fs-md);letter-spacing:-.01em}
.cs-row-meta{font-size:var(--fs-sm);color:var(--sub);margin-top:var(--s-1);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cs-row-arw{color:var(--sub);opacity:.5;font-size:var(--fs-lg)}
.cs-star{all:unset;cursor:pointer;display:inline-flex;color:var(--sub);flex-shrink:0}
.cs-star:hover{color:var(--accent-t)}
/* ♿ 누르는 영역(2026-09-27): 보이는 크기는 그대로, 손가락 영역만 44px 안팎으로 */
.cs-star{position:relative}
.cs-card .cs-star{position:absolute}
.cs-star::after,.crumbs a::after,.td-check::after,.__x::after{content:"";position:absolute;inset:-12px}
.crumbs a{position:relative}
button.td-check{position:relative!important}
.__x{position:relative}


/* ── 전역 아바타 ── */
.gw-av{border-radius:var(--r-sm);display:inline-flex;align-items:center;justify-content:center;font-weight:var(--w-black);color:#fff;flex-shrink:0;letter-spacing:-.02em;vertical-align:middle;line-height:1}
.av-name{display:inline-flex;align-items:center;gap:8px}


/* ── 페이지 전환 로딩 스피너 (느린 전환 400ms+ 시) ── */
.content{position:relative}
.content{position:relative}
/* 느린 전환(400ms+) 시 콘텐츠 영역에 페이지 골격 스켈레톤(프레임=사이드바는 유지) */
#gwLoadOv{position:absolute;inset:0;background:var(--bg);z-index:40;overflow:hidden;animation:gwFade var(--d-1) var(--ease)}
/* 🚨 크로스-도큐먼트 MPA 뷰 트랜지션 제거(2026-07-28): full 리로드/비부스트 이동에서 전환이 "invalid state"로
   중단되면(간헐적 레이스) ::view-transition 오버레이가 실제 콘텐츠를 덮어 **화면만 빈화면**(DOM엔 카드 그대로).
   "휴가 새로고침 2번째 blank" 실사고 원인. 부스트 이동은 HTMX 스왑+CSS라 이 기능과 무관(globalViewTransitions=false)
   → 제거해도 메뉴 부드러움 유지, blank만 사라짐. 재도입 금지(fetch+morph가 이미 부드러운 콘텐츠 전환 담당). */
.gw-sk{padding:var(--s-14) var(--s-14);max-width:1040px}
.gw-sk .sk-line,.gw-sk .sk-card{border-radius:var(--r-sm);background:linear-gradient(90deg,color-mix(in srgb,var(--border) 55%,transparent) 25%,color-mix(in srgb,var(--border) 90%,var(--card)) 37%,color-mix(in srgb,var(--border) 55%,transparent) 63%);background-size:280% 100%;animation:skShimmer 1.25s ease infinite}
.gw-sk .sk-line{height:14px;margin-bottom:var(--s-6)}
.gw-sk .sk-cards{display:flex;gap:14px;margin:var(--s-10) 0 var(--s-2);flex-wrap:wrap}
.gw-sk .sk-card{flex:1;min-width:150px;height:80px;border-radius:var(--r-lg)}
.gw-sk .sk-block{margin-top:var(--s-10);border:1px solid var(--border);border-radius:var(--r-lg);padding:var(--s-10)}
.gw-spin{width:34px;height:34px;border:3px solid color-mix(in srgb, var(--accent) 22%, var(--border));border-top-color:var(--accent);border-radius:50%;animation:gwSpin .7s linear infinite}
@keyframes gwSpin{to{transform:rotate(360deg)}}
@keyframes gwFade{from{opacity:0}to{opacity:1}}
@keyframes skShimmer{0%{background-position:140% 0}100%{background-position:-140% 0}}
/* 지연 프래그먼트가 «갈아끼워지는» 대신 스며들게(2026-09-21) — app.js 가 스켈레톤이 있던
   자리에만 .gw-frag-in 을 붙인다. ⚠️ translateY 만 쓴다: scale 이면 높이가 변해
   홈 위젯 메이슨리가 애니메이션 중의 높이로 계산한다. */
@keyframes gwFragIn{from{opacity:0;transform:translate3d(0,6px,0)}to{opacity:1;transform:none}}
.gw-frag-in{animation:gwFragIn var(--d-2) var(--ease)}
@media(prefers-reduced-motion:reduce){.gw-frag-in{animation:none}}
@media(prefers-reduced-motion:reduce){.gw-spin{animation-duration:1.4s}#gwLoadOv,.gw-sk .sk-line,.gw-sk .sk-card{animation:none}}


/* ── 모바일: 모달 = 바텀시트(토스식) ── */
@media(max-width:600px){
  /* 모바일 = 중앙 팝업(바텀시트 폐기, 2026-07-14 사장님) — 기본 align-items:center 유지 */
  .modal-bg{padding:var(--s-7)}
  .modal{border-radius:var(--r-xl);padding:var(--s-10) var(--s-9) calc(var(--s-9) + env(safe-area-inset-bottom))}
  .modal.modal-sm{width:100%}
}
/* 폰 폴리시 (≤600px) — 홈·마이페이지 등 공통 컴포넌트 밀도·타이포 정돈 (2026-07-14) */
@media(max-width:600px){
  .main{padding:var(--s-8) var(--s-7) var(--s-14)}
  .page-title{font-size:var(--fs-xl)}
  .page-sub{font-size:var(--fs-sm)}
  .grid{gap:9px}
  .card.stat{padding:var(--s-8) var(--s-7)}
  .card.stat.has-ic{gap:11px}
  .card.stat .card-big{font-size:var(--fs-xl)}
  .card-title{font-size:var(--fs-base)}
  .prof-hero{padding:var(--s-9) var(--s-8);gap:13px}
  .prof-hero .prof-name{font-size:var(--fs-xl)}
  .prof-hero .prof-sub{font-size:var(--fs-sm)}
  .widget{padding:var(--s-8) var(--s-8)}
}
@keyframes gwSheetIn{from{opacity:.6;transform:translateY(100%)}to{opacity:1;transform:none}}


/* ── 레이아웃 유틸리티 (인라인 style 대체 · design_system.md §10) ── */
.hstack{display:flex;align-items:center;gap:10px}
.vstack{display:flex;flex-direction:column;gap:10px}
.between{justify-content:space-between}
.wrap{flex-wrap:wrap}
.grow{flex:1}
.gap-sm{gap:6px}
.gap-lg{gap:16px}
.mt{margin-top:var(--s-7)}
.mt-lg{margin-top:var(--s-12)}


/* ── 카드 섹션 제목/부제 표준 (design_system.md §3 · 인라인 font 제각각 통일) ── */
.card-title{font-weight:var(--w-bold);font-size:var(--fs-base);margin:0 0 var(--s-5)}
.card-title.tight{margin-bottom:var(--s-2)}          /* 바로 아래 부제(.card-hint) 있을 때 */
.card-hint{color:var(--sub);font-weight:var(--w-normal);font-size:var(--fs-xs);margin:0 0 var(--s-4);line-height:1.5}
/* 장비 호스트네임 = 편집 진입점 (클릭 강조) */
.dev-editlink{color:inherit;text-decoration:none;cursor:pointer;transition:color var(--d-1) var(--ease)}
.dev-editlink .dev-editarrow{opacity:.45;transition:opacity var(--d-1) var(--ease)}
.dev-editlink:hover{color:var(--accent-t);text-decoration:underline}
.dev-editlink:hover .dev-editarrow{opacity:1;color:var(--accent-t)}

/* Tabulator+Alpine x-show 충돌 회피용 강제 숨김 */
.hidden{display:none!important}

/* 모바일 iOS 입력 자동확대 방지 — 16px 미만이면 포커스 시 줌 (2026-07-07)
   🚨 이 규칙이 `.sel` 까지 **17px 로 못박아** 상태 드롭다운이 옆 값(14px)보다 컸다.
      확대가 나는 건 **글자를 치는 칸**(text·textarea)이고 select·버튼은 아니다.
      아래 --fs-field 규칙과 하는 일이 같아 **두 벌이었다** — 그쪽으로 일원화한다. */

/* 입력 모달(gwPrompt)은 모바일에서 상단 시트 — 키보드 위로 (2026-07-07) */
@media (max-width:768px){
  .modal-bg.modal-bg-input{align-items:flex-start;padding:0}
  .modal-bg.modal-bg-input .modal{width:100%;max-width:100%;border-radius:0 0 var(--r-xl) var(--r-xl);padding:var(--s-9) var(--s-10) var(--s-10);animation:gwTopIn var(--d-3) var(--spring,ease)}
}
@keyframes gwTopIn{from{opacity:.4;transform:translateY(-12px)}to{opacity:1;transform:none}}

/* gwPrompt 커스텀 드롭다운 목록 (슬랙식 선택창, 2026-07-07) */
.gwp-list{margin-top:var(--s-5);max-height:42vh;overflow-y:auto;-webkit-overflow-scrolling:touch;border:1px solid var(--border);border-radius:var(--r-lg);display:flex;flex-direction:column}
.gwp-opt{text-align:left;padding:var(--s-6) var(--s-7);border:0;border-bottom:1px solid var(--border);background:var(--card);color:var(--text);font-size:var(--fs-md);font-family:inherit;cursor:pointer;transition:background var(--d-1)}
.gwp-opt:last-child{border-bottom:0}
.gwp-opt:active,.gwp-opt:hover{background:var(--accent-weak);color:var(--accent-t)}
.gwp-empty{padding:var(--s-7);color:var(--sub);font-size:var(--fs-base)}

/* flatpickr 스킨 — 온길 톤(--accent), 라이트/다크 자동 매칭 */
.flatpickr-calendar{background:var(--card);border:1px solid var(--border);border-radius:var(--r-lg);box-shadow:0 14px 40px rgba(0,0,0,.16);font-family:inherit}
.flatpickr-calendar.arrowTop:before,.flatpickr-calendar.arrowTop:after{border-bottom-color:var(--card)}
.flatpickr-calendar.arrowBottom:before,.flatpickr-calendar.arrowBottom:after{border-top-color:var(--card)}
.flatpickr-months .flatpickr-month,.flatpickr-current-month input.cur-year,.flatpickr-current-month .flatpickr-monthDropdown-months{color:var(--text)}
.flatpickr-current-month .flatpickr-monthDropdown-months,.flatpickr-monthDropdown-months .flatpickr-monthDropdown-month{background:var(--card);color:var(--text)}
span.flatpickr-weekday{color:var(--sub);font-weight:var(--w-bold)}
.flatpickr-months .flatpickr-prev-month svg,.flatpickr-months .flatpickr-next-month svg{fill:var(--sub)}
.flatpickr-months .flatpickr-prev-month:hover svg,.flatpickr-months .flatpickr-next-month:hover svg{fill:var(--accent)}
.flatpickr-day{color:var(--text);border-radius:var(--r-sm)}
.flatpickr-day:hover,.flatpickr-day:focus{background:var(--accent-weak);border-color:transparent}
.flatpickr-day.today{border-color:var(--accent)}
.flatpickr-day.today:hover{background:var(--accent-weak);color:var(--text)}
.flatpickr-day.selected,.flatpickr-day.selected:hover,.flatpickr-day.startRange,.flatpickr-day.endRange{background:var(--accent);border-color:var(--accent);color:#fff}
.flatpickr-day.flatpickr-disabled,.flatpickr-day.prevMonthDay,.flatpickr-day.nextMonthDay{color:var(--sub);opacity:.45}
.flatpickr-day.flatpickr-disabled:hover{background:transparent}
.numInputWrapper span.arrowUp:after{border-bottom-color:var(--sub)}
.numInputWrapper span.arrowDown:after{border-top-color:var(--sub)}

/* 인라인 편집 펜 버튼 (공용) */
.ts-pen{all:unset;cursor:pointer;color:var(--sub);display:inline-flex;padding:var(--s-2);border-radius:var(--r-xs);flex-shrink:0}
.ts-pen:hover{color:var(--accent-t);background:var(--accent-weak)}
/* 인라인 편집 손잡이 — 값 자체가 버튼이다(연필 폐기, 사장님 2026-08-31 "촌스럽거든").
   평소엔 그냥 글자, hover 에만 옅은 배경. 편집 가능하다는 신호는 이 정도면 충분하고,
   아이콘을 하나 더 세우면 좁은 화면에서 제목을 밀어낸다. */
.cf-val{cursor:text;border-radius:var(--r-xs);outline:none;-webkit-tap-highlight-color:transparent;
  transition:background var(--d-1) var(--ease),box-shadow var(--d-1) var(--ease)}
/* 🚨 배경은 **box-shadow 로 번지게** 한다 — padding+음수 margin 으로 넓히면 블록 요소(h1)가
   부모보다 커져 좁은 화면에서 가로 스크롤이 생긴다. 그림자는 레이아웃을 안 건드린다. */
.cf-val:hover{background:var(--accent-weak);box-shadow:0 0 0 5px var(--accent-weak)}
.cf-val:focus-visible{background:var(--accent-weak);
  box-shadow:0 0 0 5px var(--accent-weak),0 0 0 7px var(--accent)}
/* 🚨 **손가락엔 hover 가 없다.** 연필을 걷어낸 자리에 아무 표시도 없으면 모바일에선
   "여기 눌러도 된다"는 신호가 통째로 사라진다 — 옅은 밑줄을 항상 둔다(아이콘은 되살리지 않고).
   누르는 순간 배경이 들어와 눌렸다는 것도 알려준다. */
@media (hover:none){
  /* 🚨 밑줄에 모서리(6px)가 걸리면 **양옆이 말려 올라가 쟁반처럼** 보인다 — 입력칸으로
     오해된다(2026-09-07 사장님 실기기 캡처). 밑줄일 때는 곧게 편다. */
  .cf-val{border-radius:0;box-shadow:inset 0 -1px 0 var(--border);padding:var(--s-2) var(--s-1);margin:calc(var(--s-2) * -1) calc(var(--s-1) * -1)}
  .cf-val:active{background:var(--accent-weak);box-shadow:inset 0 -1px 0 var(--accent)}
}
/* 저장 중 — 토스트 대신 값이 살짝 흐려질 뿐. 한 글자 고칠 때마다 화면이 시끄러우면 안 된다 */
[data-cf].cf-saving{opacity:.5;pointer-events:none;transition:opacity var(--d-1) var(--ease)}

/* ===== flatpickr 커스텀 테마 (토스풍 · 온길 오렌지 · 라이트/다크 자동) ===== */
.flatpickr-calendar{background:var(--card);border:1px solid var(--border);border-radius:var(--r-xl);box-shadow:0 14px 44px rgba(0,0,0,.16);padding:var(--s-5) var(--s-6) var(--s-6);width:auto;font-family:inherit}
.flatpickr-calendar.arrowTop:before,.flatpickr-calendar.arrowTop:after,.flatpickr-calendar.arrowBottom:before,.flatpickr-calendar.arrowBottom:after{display:none}
.flatpickr-months{padding:var(--s-1) var(--s-1) var(--s-2);align-items:center}
.flatpickr-months .flatpickr-month{color:var(--text);height:36px}
.flatpickr-current-month{font-size:var(--fs-md);font-weight:var(--w-black);padding:var(--s-3) 0 0}
.flatpickr-current-month .cur-month,.flatpickr-current-month input.cur-year{font-weight:var(--w-black);color:var(--text)}
.flatpickr-current-month input.cur-year{background:transparent;border:0}
.flatpickr-monthDropdown-months{font-weight:var(--w-black);color:var(--text);background:var(--card);border-radius:var(--r-sm)}
.flatpickr-months .flatpickr-prev-month,.flatpickr-months .flatpickr-next-month{padding:var(--s-4);height:34px;width:34px;border-radius:var(--r-md);color:var(--sub);top:2px;display:inline-flex;align-items:center;justify-content:center}
.flatpickr-months .flatpickr-prev-month:hover,.flatpickr-months .flatpickr-next-month:hover{background:var(--accent-weak);color:var(--accent-t)}
.flatpickr-months .flatpickr-prev-month svg,.flatpickr-months .flatpickr-next-month svg{fill:currentColor;width:15px;height:15px}
span.flatpickr-weekday{color:var(--sub);font-weight:var(--w-bold);font-size:var(--fs-xs);text-transform:none}
.flatpickr-weekdays{margin-top:var(--s-3);height:26px}
.dayContainer{padding:var(--s-2) 0 0;width:266px;min-width:266px;max-width:266px}
.flatpickr-days{border:0;width:266px}  /* 셀 38px×7 — 원본 307.875px에 38px 셀이면 8개/줄로 요일 밀림(2026-07-23 실사고) */
.flatpickr-day{color:var(--text);border-radius:var(--r-md);height:38px;line-height:37px;max-width:38px;border:1.5px solid transparent;font-weight:var(--w-semibold);margin:var(--s-1) 0}
.flatpickr-day:hover,.flatpickr-day:focus{background:var(--accent-weak);color:var(--text);border-color:transparent}
.flatpickr-day.today{border-color:var(--accent);color:var(--accent-t);font-weight:var(--w-black)}
.flatpickr-day.today:hover{background:var(--accent-weak);color:var(--accent-t)}
.flatpickr-day.selected,.flatpickr-day.selected:hover,.flatpickr-day.startRange,.flatpickr-day.endRange{background:var(--accent);border-color:var(--accent);color:#fff;font-weight:var(--w-black);box-shadow:0 5px 14px rgba(232,100,42,.34)}
.flatpickr-day.inRange{background:var(--accent-weak);border-color:transparent;box-shadow:none;color:var(--text)}
.flatpickr-day.flatpickr-disabled,.flatpickr-day.prevMonthDay,.flatpickr-day.nextMonthDay{color:var(--sub);opacity:.4}
.numInputWrapper span.arrowUp,.numInputWrapper span.arrowDown{border:0;opacity:.6}
.numInputWrapper:hover{background:var(--accent-weak);border-radius:var(--r-sm)}
.flatpickr-time input:hover,.flatpickr-time .flatpickr-am-pm:hover{background:var(--accent-weak)}

/* flatpickr 입력창 — 앱 인풋 스타일 통일(파란 기본 포커스 제거·오렌지 포커스) */
.flatpickr-input,input.flatpickr-input{border:1px solid var(--border);border-radius:var(--r-md);padding:var(--s-4) var(--s-6);background:var(--card);color:var(--text);font-family:inherit;font-size:var(--fs-md);font-weight:var(--w-semibold);line-height:1.3;transition:border-color var(--d-2),box-shadow var(--d-2)}
.flatpickr-input:focus,.flatpickr-input.active{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-weak)}

/* 느린 액션 진행 표시 (2026-08-19) — 서버가 여러 건을 순차 처리하는 폼용.
   반응이 없으면 사람들이 버튼을 여러 번 누른다(담당 일괄 변경 20초 사례). 고유 접두 gw- 유지. */
.gw-spin-sm{display:inline-block;width:13px;height:13px;border:2px solid color-mix(in srgb, currentColor 32%, transparent);border-top-color:currentColor;border-radius:50%;animation:gwSpin .7s linear infinite;margin-right:var(--s-4);vertical-align:-2px}
form.gw-busy label,form.gw-busy .btn.ghost,form.gw-busy input:not([type=submit]){pointer-events:none;opacity:.5}
/* 화면 최상단 진행바 — 어떤 느린 액션이든 "지금 뭔가 돌고 있다"가 보이게 */
/* 본문 «처리 중» 덮개(gwBusyStart) — #main 위치에만 깔리고 사이드바·상단 바는 그대로. 0.4초 넘는 저장·제출·첨부에서만 */
#gwBusyOv{position:fixed;z-index:150;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--s-5);
  background:color-mix(in srgb,var(--bg) 62%,transparent);opacity:0;pointer-events:none;transition:opacity var(--d-2) var(--ease)}
#gwBusyOv.on{opacity:1;pointer-events:auto;cursor:progress}
.gw-busy-spin{width:36px;height:36px;border-radius:var(--r-pill);border:3px solid color-mix(in srgb,var(--accent) 22%,transparent);
  border-top-color:var(--accent);animation:gw-spin .8s linear infinite}
.gw-busy-msg{font-size:var(--fs-base);font-weight:var(--w-semibold);color:var(--text);background:var(--card);
  padding:var(--s-3) var(--s-7);border-radius:var(--r-pill);box-shadow:0 2px 10px rgba(0,0,0,.08)}
@media (prefers-reduced-motion:reduce){.gw-busy-spin{animation-duration:2.4s}}
#gwTopbar{position:fixed;top:0;left:0;height:3px;width:0;background:var(--accent);z-index:9999;opacity:0;transition:width var(--d-3) var(--ease),opacity var(--d-2);pointer-events:none}
#gwTopbar.on{opacity:1}

/* ── 휴가 요약(lvb-) ── 접두를 붙인 이유: .bar/.card 류 공용 이름은 다른 화면과 충돌한다 */
.banner.warn{background:rgba(245,158,11,.14);color:#a86a06}
.lvb-hero{padding:var(--s-9) var(--s-10)}
.lvb-top{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;flex-wrap:wrap}
.lvb-big{font-size:var(--fs-3xl);font-weight:var(--w-black);letter-spacing:-.02em;line-height:1.1}
.lvb-big .unit{font-size:var(--fs-md);font-weight:var(--w-semibold);color:var(--sub);margin-left:var(--s-2)}
.lvb-parts{display:flex;gap:6px;flex-wrap:wrap;align-items:center}
.lvb-bar{position:relative;height:8px;border-radius:var(--r-pill);background:var(--bg);overflow:hidden;margin:var(--s-7) 0 var(--s-4)}
.lvb-fill{position:absolute;left:0;top:0;height:100%;border-radius:var(--r-pill);background:var(--accent);
  transition:width .5s var(--ease)}
.lvb-bar.mini{height:5px;margin:var(--s-5) 0 var(--s-3)}
.lvb-fill.warn{background:var(--warn)}
.lvb-dday{display:inline-flex;align-items:center;gap:4px;font-size:var(--fs-xs);font-weight:var(--w-black);
  padding:var(--s-1) var(--s-4);border-radius:var(--r-pill);background:var(--bg);color:var(--sub);margin-left:var(--s-3)}
.lvb-dday.soon{background:rgba(245,158,11,.16);color:#a86a06}
.lvb-exp{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.lvb-exp .lvb-act{margin-left:auto}
@media (max-width:560px){.lvb-big{font-size:var(--fs-2xl)}.lvb-exp .lvb-act{margin-left:0;width:100%}}
.lvb-why summary::-webkit-details-marker{display:none}
.lvb-why summary::after{content:"▾";float:right;color:var(--sub);font-weight:var(--w-normal);transition:var(--d-2) var(--ease)}
.lvb-why[open] summary::after{transform:rotate(180deg);display:inline-block}

/* ── 팀 휴가 캘린더(lvcal-) ── 가로 스크롤: 인원×일수 격자는 좁은 화면에서 반드시 넘친다 */
.lvcal-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
.lvcal{border-collapse:separate;border-spacing:0;font-size:var(--fs-xs);min-width:100%}
.lvcal th,.lvcal td{padding:0;text-align:center;white-space:nowrap}
.lvcal .nm{position:sticky;left:0;z-index:2;background:var(--card);text-align:left;
  padding:0 var(--s-6) 0 var(--s-1);font-weight:var(--w-bold);font-size:var(--fs-sm);min-width:64px;width:72px}   /* 폭 고정 — 남는 폭이 이름 열로 몰려 날짜 칸이 오른쪽에 뭉쳤다 */
.lvcal thead .nm{background:var(--card)}
.lvcal .dh{min-width:22px;color:var(--sub);font-weight:var(--w-bold);line-height:1.35;padding-bottom:var(--s-3)}
.lvcal .dh.off{color:var(--sub);font-weight:var(--w-normal)}
.lvcal .dh.now{color:var(--accent-t)}
.lvcal .dh small{display:block;font-size:var(--fs-micro);font-weight:var(--w-semibold);opacity:.8}
.lvcal td.cell{height:22px;border-top:1px solid var(--hair)}
.lvcal td.cell.off{background:var(--bg)}
.lvcal td.cell.now{box-shadow:inset 1px 0 0 var(--accent),inset -1px 0 0 var(--accent)}
.lvcal .mk{display:block;height:14px;margin:var(--s-2) var(--s-1);border-radius:var(--r-xs)}
.lvcal .mk.a{background:var(--accent)}
.lvcal .mk.c{background:var(--ok)}
.lvcal .mk.s{background:#8B5CF6}
.lvcal .mk.h{background:linear-gradient(180deg,var(--accent) 50%,transparent 50%)}
.lvcal .mk.wait{background:none;border:1.5px dashed var(--accent);opacity:.85}
.lvcal-lg{display:flex;gap:13px;flex-wrap:wrap;align-items:center;margin-top:var(--s-6);font-size:var(--fs-xs);color:var(--sub)}
.lvcal-lg i{display:inline-block;width:12px;height:9px;border-radius:var(--r-xs);margin-right:var(--s-2);vertical-align:-1px}

/* ── 휴가 신청 폼 실시간 잔여(lvf-) ── */
.lvf-calc{display:flex;align-items:baseline;gap:7px;flex-wrap:wrap;font-size:var(--fs-base);font-weight:var(--w-bold);
  padding:var(--s-5) var(--s-7);border-radius:var(--r-md);background:var(--bg);color:var(--text)}
.lvf-calc.over{background:rgba(239,68,68,.1);color:#d33f3f}
.lvf-calc .lvf-ar{color:var(--sub);font-weight:var(--w-semibold)}
.lvf-calc b{font-size:var(--fs-md);color:var(--accent-t)}
.lvf-calc.over b{color:#d33f3f}
.lvf-calc .lvf-need{font-size:var(--fs-sm);font-weight:var(--w-semibold);color:var(--sub)}
.lvf-calc .lvf-warn{margin-left:auto;font-size:var(--fs-sm);font-weight:var(--w-bold)}

/* ── 표준 컴포넌트 (2026-08-25) ── 인라인으로 반복되던 패턴을 승격 ── */
/* 빈 상태 — <td colspan=N class="empty">…</td> (인라인 text-align:center;padding 73곳 대체) */
.empty{text-align:center;padding:var(--s-16) var(--s-8);color:var(--sub);font-size:var(--fs-base)}
.empty.sm{padding:var(--s-10) var(--s-7);font-size:var(--fs-sm)}
/* 버튼 크기 변형 — .btn 에 인라인으로 padding+font-size 를 매번 쓰던 것 */
.btn.sm{padding:var(--s-3) var(--s-7);font-size:var(--fs-sm)}
.btn.xs{padding:var(--s-2) var(--s-6);font-size:var(--fs-sm)}
/* 안내 블록 — card + border-left 강조를 손으로 그리던 패턴 */
.note{background:var(--card);border:1px solid var(--border);border-left:3px solid var(--accent);
  border-radius:var(--r-lg);padding:var(--s-7) var(--s-9);font-size:var(--fs-base);line-height:1.65}
.note.warn{border-left-color:var(--warn)}
.note.ok{border-left-color:var(--ok)}
.note .note-t{display:block;font-weight:var(--w-black);margin-bottom:var(--s-3)}

/* ══════════════════════════════════════════════════════════════════════════
   앱처럼 (사장님 2026-08-31: "모바일 버전이나 웹버전을 어플리케이션 처럼")
   껍데기(PWA 설치·아이콘·SW·하단 탭바·시트)는 이미 있다. 웹 티가 나는 건 **감촉** 쪽이라
   그 지점만 고른다. 화면 구조는 안 건드린다.
   ══════════════════════════════════════════════════════════════════════════ */

/* ① 회색/파란 탭 하이라이트 — 안드로이드에서 뭘 눌러도 네모가 번쩍인다. 앱에는 없는 것. */
html{-webkit-tap-highlight-color:transparent;-webkit-text-size-adjust:100%;text-size-adjust:100%}

/* ② 스크롤 고무줄 제어 — **뺐다**(2026-09-06 사장님 "폰에서 아래로 스크롤이 안 되네").
   `overscroll-behavior` 는 원래 체이닝·당겨서새로고침만 막는 값이지만, 실제 기기에서
   스크롤이 안 된다는 보고가 나온 이상 **장식이 기본 기능보다 앞설 수 없다.**
   앱 느낌은 다른 것(탭 반응·safe-area·전환)으로도 충분하다. 재도입하려면 실기기 확인 먼저. */

/* ③ 크롬(탭바·시트·앱바)은 길게 눌러도 글자가 선택되지 않는다 — 앱 UI 는 텍스트가 아니다.
   🚨 **본문은 절대 건드리지 않는다.** 값을 복사하는 건 실제로 쓰는 동작이다. */
.tabbar,.sheet-grid,.sheet-grab,.appbar-title,.seg-tabs,.pill,.badge{
  -webkit-user-select:none;user-select:none;-webkit-touch-callout:none}

/* ④ 누르면 즉시 반응 — 앱이 빠르게 느껴지는 건 실제 속도보다 **눌린 티**가 나기 때문이다.
   화면 전환을 기다리는 동안 아무 일도 안 일어나면 그게 웹 느낌이다. */
/* 🚨 누름 반응은 **포인터 종류를 가리지 않는다.** 2026-09-21 까지 이 규칙이 통째로
   @media(hover:none) 안에 있어서, 마우스로 카드를 눌러도 아무 일도 일어나지 않았다.
   «먹었다»는 신호가 없으면 사용자는 한 번 더 누른다 — 그게 웹 느낌의 정체다.
   ⚠️ 표 행(tr)에는 걸지 않는다: transform 은 컨테이닝 블록을 만들어 sticky 헤더와
      행 안의 드롭다운 위치를 무너뜨린다. */
.card[onclick],a.card{transition:transform var(--d-1) var(--ease)}
.card[onclick]:active,a.card:active{transform:scale(.985)}

@media(hover:none){
  /* 손가락은 더 큰 반응이 있어야 눌린 걸 안다(커서가 없으니 위치 단서도 없다) */
  .tabbar .tab:active{background:var(--bg);transform:scale(.94)}
  .tabbar .tab{transition:transform var(--d-1) var(--ease),background var(--d-1) var(--ease)}
  .btn:active{transform:scale(.97)}
  .sheet-item:active{transform:scale(.985)}
  .btn{transition:transform var(--d-1) var(--ease)}
}

/* ⑤ iOS 는 글자 16px 미만인 입력을 누르면 **화면을 확대**하고 되돌리지 않는다.
   🚨 예전엔 여기서 입력칸만 16px 로 올렸는데, 주변 본문이 12px 이라 **입력칸만 튀어** 보였다
      (사장님 2026-09-04 "폰트크기랑 어색한데?"). 이제 본문 눈금이 모바일에서 한 단 올라가
      14.5px 이므로 16px 입력이 자연스럽게 얹힌다 — 값을 --fs-field 하나로 모았다.
   🚨 `!important` 는 여기서만 쓴다. 템플릿에 인라인 font-size 가 붙은 입력이 있어
      일반 규칙으론 안 이긴다. 이건 취향이 아니라 **화면이 확대된 채 굳는 기능 버그**라
      덮는 게 맞다. 체크박스·라디오·range 는 글자가 아니라 제외. */
@media(max-width:768px){
  /* 🚨 **select 는 뺀다.** iOS 가 화면을 확대하는 건 글자를 치는 칸(text/textarea)이고,
     select 는 네이티브 피커가 뜬다. 여기 넣어 뒀더니 select 만 16px 로 튀어
     **나란한 버튼(14px)과 어긋났다**(사장님 2026-09-04 프로젝트 상세 유형·고객사 select). */
  input:not([type=checkbox]):not([type=radio]):not([type=range]),
  textarea{font-size:var(--fs-field)!important}
}

/* ⑥ 홈 화면에서 연 경우(설치본)만 — 브라우저 주소창이 없으니 상단이 허전하다.
   앱바를 조금 낮추고 하단 여백을 홈 인디케이터에 맞춘다. */
@media(display-mode:standalone){
  .content{padding-bottom:calc(var(--s-32) + env(safe-area-inset-bottom))}
  /* 당겨서 새로고침 차단도 같이 뺐다 — 위와 같은 이유(2026-09-06) */
}

/* ══════════════════════════════════════════════════════════════════════════
   화면 전환 애니메이션 (사장님 2026-08-31)
   🚨 **View Transition API 는 안 쓴다.** 이 코드베이스에 사고가 둘 있다:
      ① 크로스-도큐먼트 MPA VT → 전환이 "invalid state"로 중단되면 ::view-transition 오버레이가
        실제 콘텐츠를 덮어 **화면만 빈 화면**("휴가 새로고침 2번째 blank", 2026-07-28)
      ② htmx globalViewTransitions → #main 스왑과 지연 프래그먼트 스왑이 각각 페이드를 걸어
        **iOS 에서 두 번 깜빡**
      그래서 브라우저에 전환을 맡기지 않고 **스왑이 끝난 뒤 CSS 로만** 애니메이션한다.
      실패해도 최악이 "애니메이션이 안 뜬다"이지 화면이 사라지지 않는다.
   ══════════════════════════════════════════════════════════════════════════ */
@keyframes gwNavIn{from{opacity:0;transform:translate3d(0,9px,0)}to{opacity:1;transform:none}}
@keyframes gwNavBack{from{opacity:0;transform:translate3d(0,-7px,0)}to{opacity:1;transform:none}}
/* 앞으로 갈 땐 올라오며, 뒤로 갈 땐 내려오며 — 방향이 있어야 "이동했다"로 읽힌다 */
#main.gw-nav-in{animation:gwNavIn var(--d-2) var(--ease)}
#main.gw-nav-back{animation:gwNavBack var(--d-2) var(--ease)}
/* 움직임을 줄이라고 설정한 사람에겐 걸지 않는다(멀미·전정기관 이슈) */
@media(prefers-reduced-motion:reduce){#main.gw-nav-in,#main.gw-nav-back{animation:none}}

/* 글줄 안에 얹는 아이콘 — 크기를 **글자에 맞춘다**(1em). 아이콘마다 px 를 박으면
   글자 눈금을 만들어 놓고 아이콘만 또 제각각이 된다(2026-09-04 이모지 정리).
   stroke:currentColor 라 글자색을 그대로 따라간다 — 이모지가 못 하던 일이다. */
.ic{width:1em;height:1em;vertical-align:-.14em;stroke-width:2.5;flex:none;display:inline-block}

/* 모바일 카드 목록 — 표를 옆으로 밀지 않게(2026-09-04) */
.gcards{display:none;flex-direction:column;gap:var(--s-2)}
.gcard{background:var(--card);border:1px solid var(--border);border-radius:var(--r-lg);
  padding:var(--s-5) var(--s-6);cursor:pointer;transition:background var(--d-1) var(--ease),transform var(--d-1) var(--ease)}
.gcard:active{background:var(--bg);transform:scale(.99)}
.gcard-top{display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);
  margin-bottom:var(--s-2)}
.gcard-code{font-size:var(--fs-sm);font-weight:var(--w-black);color:var(--accent-t);
  white-space:nowrap}
.gcard-right{font-size:var(--fs-sm);flex:none}
.gcard-title{font-size:var(--fs-md);font-weight:var(--w-bold);line-height:1.4;
  word-break:keep-all}
/* 제목 칸 안의 링크는 카드가 통째로 눌리므로 색만 물려받는다 */
.gcard-title a{color:inherit;text-decoration:none}
.gcard-meta{display:flex;align-items:center;flex-wrap:wrap;gap:var(--s-1) var(--s-3);
  margin-top:var(--s-3);font-size:var(--fs-sm);color:var(--sub)}
.gcard-sep{width:var(--s-hair);height:10px;background:var(--border);display:inline-block}
.gcard-empty{padding:var(--s-10) 0;text-align:center;color:var(--sub);font-size:var(--fs-base)}

/* 항목 추가 줄(할일 등) — 프로젝트·기술지원 **공용**.
   🚨 이 규칙이 기술지원 상세 안에만 있었다. 같은 클래스를 두 화면이 쓰는데 CSS 는 한쪽에만
      있어서, 프로젝트 상세에선 아예 안 걸리고 있었다(2026-09-04). 공용 자리로 옮긴다. */
.ts-add-row .field input{height:42px}
.ts-add-row .btn{height:42px;padding:0 var(--s-9);font-size:var(--fs-md)}
@media(max-width:768px){
  /* 🚨 폰에서 한 줄에 밀어 넣으면 제목 칸이 40px 로 찌그러져 **글자를 못 친다**.
     제목은 한 줄 통째로 쓰고, 마감·담당·추가를 그 아래 한 줄로 내린다.
     현장에서 할일을 넣는 건 자주 하는 동작이라 여기가 막히면 안 된다. */
  .ts-add-row{flex-wrap:wrap;align-items:flex-end}
  .ts-add-row > .field:first-of-type{flex:1 1 100%!important;width:100%!important;max-width:none!important}
  /* 🚨 「추가」가 남는 폭을 다 먹어 **마감·담당보다 도드라졌다** — 주 버튼이라도 옆 칸들과
     같은 급으로 보여야 시선이 입력칸으로 간다(2026-09-07 사장님 지적).
     늘리지 않고 제 크기로 둔다. */
  .ts-add-row > .btn{flex:0 0 auto}
  /* KPI 카드가 홀수 개면 마지막 한 장이 반 칸만 차지해 허전하다 — 통째로 쓴다.
     (지표 카드에만 건다. 일반 카드 목록은 2열 그대로가 맞다) */
  .grid > .card.stat:last-child:nth-child(odd){grid-column:1 / -1}
}

/* 메타 카드의 편집 컨트롤 — 폰에서는 접어 둔다(2026-09-06).
   조회할 땐 상태·고객사만 보면 되는데 편집용 select 가 늘 펼쳐져 **6줄을 먹고 있었다.**
   데스크톱은 그대로 편다 — 공간이 있고 여기서 바로 고치는 게 빠르다. */
.meta-edit-btn{display:none}
@media(max-width:768px){
  #pj-meta-card .meta-edit,#ts-meta-card .meta-edit{display:none!important}
  #pj-meta-card.editing .meta-edit,#ts-meta-card.editing .meta-edit{display:inline-flex!important}
  /* 🚨 `margin-left:auto` 만으로는 **다음 형제가 있으면 끝으로 안 간다** — 상태 바로 옆에
     붙어 버렸다. flex 순서를 마지막으로 보내고 남는 폭을 앞에서 밀어낸다. */
  .meta-edit-btn{display:inline-flex;align-items:center;order:99;margin-left:auto;
    background:none;border:1px solid var(--border);border-radius:var(--r-pill);
    color:var(--sub);font-family:inherit;font-size:var(--fs-sm);font-weight:var(--w-bold);
    padding:var(--s-1) var(--s-5);cursor:pointer}
  .editing .meta-edit-btn{border-color:var(--accent);color:var(--accent-t)}
}

/* 상세 화면 상단 버튼(스레드↗ · 목록) — 폰에서 제목 줄 오른쪽에 붙인다(2026-09-07).
   .page-head 는 모바일에서 세로로 서기 때문에 이 버튼들이 **한 줄을 통째로** 먹고 있었다.
   위쪽 한 줄은 폰에서 제일 비싼 자리다. 상세 화면(.dt-head)만 가로를 유지한다. */
@media(max-width:768px){
  .page-head.dt-head{flex-direction:row;align-items:flex-start;gap:var(--s-4)}
  .dt-head > :first-child{flex:1;min-width:0}
  .dt-actions{flex:none;align-items:flex-start}
  /* 세로로 쌓았더니 제목 1줄일 때 **오른쪽이 들쭉날쭉**해졌다(2026-09-07 실기기).
     가로로 되돌리되 아주 작게 — 제목이 길면 알아서 줄바꿈된다. */
  .dt-actions{flex-direction:row;gap:var(--s-2);align-items:center}
  .dt-actions .btn{padding:var(--s-2) var(--s-3);font-size:var(--fs-xs);white-space:nowrap}
}

/* 기술지원 상세 헤더 — 데스크톱은 지금 그대로(세로 스택) */
.ts-head{display:flex;flex-direction:column;align-items:stretch;gap:0}
/* 폰에서는 **티켓 카드**로 압축(2026-09-07 사장님 선택).
   제목이 22px 페이지 제목 스타일이었는데, 이건 페이지 이름이 아니라 **문의 내용**이다 —
   내용은 본문 크기가 맞다. 그리고 마감·상태·담당이 각각 한 줄씩 3줄(94px)을 먹고 있었다. */
@media(max-width:768px){
  /* 🚨 `align-items:center` 는 **각 항목을 제 높이의 가운데**에 두므로, 높이가 조금씩 다른
     항목끼리 글자가 위아래로 어긋난다(실측 top 158/163/168). 메타 줄처럼 글자가 나란히
     읽혀야 하는 줄은 **바닥선(baseline)** 을 맞춘다. */
  .page-head.ts-head{flex-flow:row wrap;align-items:baseline;
    column-gap:var(--s-4);row-gap:var(--s-2)}
  .ts-head > .page-sub{order:1;flex:1 1 100%;margin:0}      /* 고객사·문의자를 맨 위로 */
  .ts-head > .ts-head-top{order:2;flex:1 1 100%}            /* 제목 + 버튼 */
  /* 🚨 셋이 한 줄에 들어가려면 **폭을 안 늘려야** 한다 — 기본이 블록이라 담당 줄이 100%를
     잡고 다음 줄로 밀렸다. flex 아이템을 내용 폭으로 고정한다. */
  /* 🚨 한 줄에 밑줄 텍스트·테두리 상자·맨 텍스트·버튼이 섞이면 **바닥선이 안 맞는다.**
     같은 높이 상자로 맞추고 가운데 정렬한다(2026-09-07 실기기 "라인 맞추는거"). */
  .ts-head > #ts-deadline-wrap,
  .ts-head > #ts-status-wrap,
  .ts-head > #ts-eng-wrap{order:3;margin:0;flex:0 0 auto;width:auto;
    display:flex;align-items:center;min-height:30px}
  /* 제목·고객사 줄은 baseline 이 아니라 한 줄 통째로 차지해야 한다 */
  .ts-head > .page-sub,.ts-head > .ts-head-top{align-self:stretch}
  .ts-head > #ts-deadline-wrap .tc-view,
  .ts-head > #ts-eng-wrap .tc-view{align-items:center;min-height:30px}
  .ts-head #ts-status-wrap form{align-items:center}
  /* 🚨 상태 드롭다운의 **진짜 요소는 select 가 아니다** — data-opt-select 가 만든
     `button.sel.cs-btn` 이 화면에 보이는 것이고, select 는 0x0 으로 숨겨져 있다.
     그래서 select 에만 건 규칙이 안 먹어 혼자 17px/700 로 크게 남아 있었다
     (옆의 담당·마감 값은 14px). 실제 요소에 건다(2026-09-07 사장님 지적). */
  .ts-head #ts-status-wrap .sel,
  .ts-head #ts-status-wrap .cs-btn{width:auto;
    padding:var(--s-1) var(--s-6) var(--s-1) var(--s-3);
    font-size:var(--fs-base);font-weight:var(--w-bold);border-radius:var(--r-sm);
    background-position:right var(--s-2) center}
  .ts-head #ts-status-wrap .cs-label{flex:0 0 auto}
  .ts-head #ts-eng-wrap .tc-view{gap:var(--s-2)}
  .ts-head #ts-eng-wrap .btn{padding:var(--s-1) var(--s-3);font-size:var(--fs-xs)}
  /* 제목은 문의 내용 — 본문급으로 낮춘다 */
  .ts-head .page-title{font-size:var(--fs-lg)}
}

/* 프로젝트 상세도 기술지원과 같은 「티켓 카드」 크기로(2026-09-07 사장님 "똑같이 적용").
   제목은 페이지 이름이 아니라 **그 프로젝트가 무슨 일인지**다 — 내용이니 본문급으로. */
@media(max-width:768px){
  .page-head.dt-head .page-title{font-size:var(--fs-lg)}
  /* 기간·D-day·담당이 두 줄로 갈라져 있었다 — 한 줄로 모으고 바닥선을 맞춘다 */
  #pj-period-wrap .tc-view{align-items:baseline;row-gap:0;column-gap:var(--s-3)}
  #pj-period-wrap .av-name{gap:var(--s-2)}
}

/* 정기점검 상세 — 폰(2026-09-07).
   🚨 단계바가 내용 480px / 보이는 폭 374px 라 **106px 가 잘린다.** 스크롤바를 숨겨 놔서
      더 있다는 것도 모른다 — 4·5단계가 없는 것처럼 보인다.
      ①오른쪽 끝에 옅은 그라데이션으로 "더 있음"을 알리고 ②현재 단계는 JS 가 끌어온다. */
@media(max-width:768px){
  .mt-flow{position:relative;scroll-behavior:smooth}
  .mt-flow-wrap{position:relative}
  .mt-flow-wrap::after{content:"";position:absolute;top:0;right:0;bottom:0;width:28px;
    pointer-events:none;background:linear-gradient(to right,transparent,var(--card))}
  /* 제목은 다른 상세와 같은 단으로 — 프로젝트·기술지원은 이미 내렸다 */
  .page-head .page-title{font-size:var(--fs-lg)}
}

/* 목록 화면의 지표 카드 — 폰에서는 **한 줄 칩**으로(2026-09-07).
   실측(440px): KPI 가 177px 를 먹고, 그 값은 바로 위 page-sub(「내 프로젝트 14건 ·
   진행 11 · 완료 3」)와 **거의 같은 말**이다. 첫 카드까지 618px — 화면의 65% 가
   목록이 아니라 머리말이었다. 정보는 남기고 자리만 줄인다. */
@media(max-width:768px){
  /* 🚨 내용 폭(`flex:0 0 auto`) 알약이라 **칸마다 폭이 달랐고**(「마감 임박·경과」만 넓음)
     오른쪽에 빈 공간이 남았다(2026-09-21 실기기). 숫자를 나란히 비교하는 줄에서 칸 폭이
     다르면 «어느 게 큰지»가 폭으로도 읽혀 오독을 만든다 — 폭은 정보가 아니다.
     → **한 줄 유지 + 균등 분할**(flex:1 1 0). 긴 라벨은 칸 안에서 줄바꿈하고, stretch 라
       카드 높이는 서로 맞는다. 실측(라벨 실폭 vs 칸폭):
         402px 3칸 121px·1줄 / 402px 4칸 90px·1줄 / 390px 4칸 87px(「위험 (마감 경과)」만 2줄)
         → 좁은 폰에서 줄 높이가 45→60px 이 될 뿐 **잘림·가로넘침 없음**, 높이 편차 0.
     ⚠️ nowrap 이라 칸이 늘면(5개 이상) 좁아진다 — 늘릴 땐 여기 실측부터 다시. */
  .grid.list-kpi{display:flex;flex-wrap:nowrap;gap:var(--s-2);align-items:stretch}
  .grid.list-kpi > .card.stat{flex:1 1 0;min-width:0;display:flex;align-items:center;
    justify-content:center;padding:var(--s-3);border-radius:var(--r-lg);margin:0}
  .grid.list-kpi .wg-ic,.grid.list-kpi .card-sub{display:none}   /* 아이콘·부연은 뺀다 */
  .grid.list-kpi .stat-body{min-width:0;text-align:center}
  .grid.list-kpi .card-label{font-size:var(--fs-xs);color:var(--sub);line-height:1.3;margin:0}
  .grid.list-kpi .card-big{font-size:var(--fs-md);font-weight:var(--w-black);line-height:1.2}
  .grid.list-kpi .card-big .unit{font-size:var(--fs-xs);font-weight:var(--w-semibold)}
}

/* 목록 필터 접기 버튼 — 폰에서만 보인다(2026-09-07) */
.flt-bar{display:none}
@media(max-width:768px){
  /* 🚨 바와 «예약 자리»는 **같은 박스**여야 한다 — 높이 var(--flt-h), 마진 0.
     마진으로 여백을 주면 이웃과 겹침(margin collapsing)이 상태마다 달라져 몇 px 씩 어긋난다
     (실측 −9px). 높이 안에서 버튼을 세로 가운데 두면 보이는 여백은 그대로다. */
  .flt-bar{display:flex;align-items:center;height:var(--flt-h);margin:0}
  .flt-btn{flex:1;display:flex;align-items:center;justify-content:space-between;
    background:var(--card);border:1px solid var(--border);border-radius:var(--r-md);
    color:var(--text);font-family:inherit;font-size:var(--fs-base);font-weight:var(--w-bold);
    padding:var(--s-4) var(--s-6);cursor:pointer;text-align:left}
  .flt-btn:active{background:var(--bg)}
  /* 🚨 **접는 일은 CSS 가 먼저 한다.** app.js 는 </body> 앞에서 로드되므로 그때까지
     툴바가 펼쳐진 채 그려졌다가 접혔다 — 폰에서 페이지를 열 때마다 필터가 3줄→1줄로
     줄며 **아래 내용이 통째로 점프**했다(2026-09-21 실기기). 첫 페인트부터 접어 둔다.
     🔑 선택자는 app.js 의 boot() 와 **글자 그대로 같아야** 한다 — 갈라지면 한쪽만 적용돼
        «툴바가 영영 안 보이는» 화면이 생긴다. (app.js: '.grid.list-kpi ~ .toolbar, .list-kpi + .toolbar')
     ⚠️ .gw-fold 는 base.html head 가 달고, app.js 가 .flt-bar 를 못 만들면 2.5초 뒤 스스로 걷는다. */
  /* ① 접힘 = **자리를 비워 두되 보이지 않게.** 그냥 display:none 하면 나중에 생기는
        버튼(46px)이 목록을 아래로 밀어 «작은 점프»가 남는다(2026-09-21 실기기 2차).
        높이는 --flt-h 한 곳에서만 정한다 — 두 군데면 언젠가 어긋난다.
     🚨 margin 만 !important — 템플릿이 `style="margin-top:…"` 를 인라인으로 주는 곳이 있어
        (예: techsupport.html) 그것까지 눌러야 예약 높이가 정확히 46px 이 된다. */
  .gw-fold .grid.list-kpi ~ .toolbar:not([data-open="1"]),
  .gw-fold .list-kpi + .toolbar:not([data-open="1"]){
    display:block;height:var(--flt-h);margin:0!important;padding:0;overflow:hidden;visibility:hidden}
  /* ② 버튼이 실제로 생기면 자리를 **완전히 넘긴다** — 둘이 같이 차지하면 오히려 두 배가 된다.
        (app.js 가 .flt-bar 를 .toolbar **바로 앞**에 끼우므로 인접 형제로 잡힌다) */
  /* 🚨 ① 이 `.grid.list-kpi ~` 라 클래스가 하나 더 많다 — 여기서 `.flt-bar +` 만 쓰면
        **특이도가 낮아 져서** 예약이 안 풀리고 버튼 높이만큼 또 밀린다(45px, 실측으로 잡음).
        같은 조상 사슬을 그대로 적고 `~ .flt-bar ~` 를 끼워 ① 보다 높게 만든다. */
  .gw-fold .grid.list-kpi ~ .flt-bar ~ .toolbar:not([data-open="1"]){display:none}
  /* ③ 펼쳤을 때는 원래대로 */
  .gw-fold .grid.list-kpi ~ .toolbar[data-open="1"],
  .gw-fold .list-kpi + .toolbar[data-open="1"]{display:flex;height:auto;visibility:visible}
}

/* 고객사 유입 경로 배지 — 관계사 경유 표시(2026-09-07) */
.cs-ch{display:inline-block;margin-left:var(--s-3);padding:var(--s-1) var(--s-3);
  border-radius:var(--r-sm);background:var(--accent-weak,#FDEDE6);color:var(--accent-t);
  font-size:var(--fs-xs);font-weight:var(--w-bold);vertical-align:middle;white-space:nowrap}

/* ===== 내 경비 (2026-09-24 재디자인) =====
   휴가 화면(lvb-hero)과 같은 언어: 대표 숫자 하나 + 한 줄 요약 + 분류 막대 + 확인할 것.
   분류 색(--c)은 막대·범례·표 아이콘·입력 칩이 **같은 값**을 쓴다(뷰의 _EXP_CAT 과 짝). */
.c-meal{--c:var(--accent)} .c-fuel{--c:#3B82F6} .c-move{--c:#8B5CF6} .c-stay{--c:#06B6D4} .c-office{--c:var(--ok)} .c-etc{--c:#94A3B8}
.exh{padding:var(--s-10) var(--s-12);margin-bottom:var(--s-7)}
.exh-top{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--s-8);flex-wrap:wrap}
.exh-lbl{font-size:var(--fs-sm);font-weight:var(--w-bold);color:var(--sub)}
.exh-big{font-size:var(--fs-3xl);font-weight:var(--w-black);letter-spacing:-.025em;line-height:1.15;margin-top:var(--s-3);font-variant-numeric:tabular-nums}
.exh-big .unit{font-size:var(--fs-lg);font-weight:var(--w-semibold);color:var(--sub);margin-left:var(--s-2)}
.exh-sub{margin-top:var(--s-4);font-size:var(--fs-base);color:var(--sub);font-variant-numeric:tabular-nums}
.exh-sub b{color:var(--text);font-weight:var(--w-bold)}
.exh-nav{display:inline-flex;align-items:center;gap:var(--s-2);background:var(--bg);border-radius:var(--r-pill);padding:var(--s-2)}
.exh-nav .icon-btn{width:30px;height:30px;border:0;background:var(--card);border-radius:var(--r-pill);box-shadow:var(--shadow)}
.exh-nav .icon-btn.off{opacity:.35;pointer-events:none;box-shadow:none;background:none}
.exh-nav .icon-btn svg{width:16px;height:16px}
.exh-ym{min-width:84px;text-align:center;font-weight:var(--w-bold);font-size:var(--fs-base);font-variant-numeric:tabular-nums}
/* 경비 월 선택 팝업(9/30) — 연도 이동 + 12개월 격자. 기반 = .dropdown/.dropdown-pop */
.ymp-btn{border:0;background:none;color:inherit;cursor:pointer;padding:var(--s-2) var(--s-3);border-radius:var(--r-pill)}
.ymp-btn:hover{background:var(--card)}
.ymp{left:50%;transform:translateX(-50%);width:min(260px,calc(100vw - var(--s-16)));padding:var(--s-5)}
@media (min-width:769px){.ymp{left:auto;right:calc(-1 * var(--s-20));transform:none}}  /* 데스크톱: 월 이동 막대 오른쪽 끝에 맞춤(가운데면 카드 밖으로 샌다) */
.ymp-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--s-4)}
.ymp-head b{font-size:var(--fs-base)}
.ymp-head .icon-btn.off{opacity:.35;pointer-events:none}
.ymp-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s-2);margin:var(--s-4) 0}
.ymp-m{display:block;text-align:center;padding:var(--s-4) 0;border-radius:var(--r-sm);font-size:var(--fs-sm);color:var(--sub)}
.ymp-m.has{color:var(--text);font-weight:var(--w-bold)}
.ymp-m:hover,.ymp-all:hover{background:var(--accent-weak);color:var(--accent-t)}
.ymp-m.on,.ymp-all.on{background:var(--accent);color:var(--on-accent)}
.ymp-m.off{opacity:.35;pointer-events:none}
.ymp-all{display:block;text-align:center;padding:var(--s-3);border-radius:var(--r-sm);font-size:var(--fs-sm);background:var(--bg);margin-top:var(--s-2)}
.exh-bar{display:flex;gap:2px;height:8px;border-radius:var(--r-pill);overflow:hidden;background:var(--bg);margin:var(--s-10) 0 var(--s-5)}
.exh-bar i{display:block;height:100%;background:var(--c)}
.exh-legend{display:flex;flex-wrap:wrap;gap:var(--s-3) var(--s-8);font-size:var(--fs-sm);color:var(--sub)}
.exh-legend span{display:inline-flex;align-items:center;gap:var(--s-3)}
.exh-legend i{width:8px;height:8px;border-radius:50%;display:inline-block;background:var(--c)}
.exh-legend b{color:var(--text);font-weight:var(--w-bold);font-variant-numeric:tabular-nums}
.exh-foot{display:flex;align-items:center;gap:var(--s-4);flex-wrap:wrap;margin-top:var(--s-9);padding-top:var(--s-8);border-top:1px solid var(--border)}
.exh-foot .grow{flex:1}
/* 상태 알약 톤 — 공용 .statuspill(기본=accent) 위에 색만 얹는다. 뷰 _EXP_TONE 값과 짝 */
.statuspill.ok{background:rgba(16,185,129,.12);color:var(--st-ok)}
.statuspill.b{background:rgba(59,130,246,.12);color:#2563EB}
.statuspill.warn{background:rgba(245,158,11,.14);color:#B45309}
.statuspill.err{background:rgba(239,68,68,.12);color:#DC2626}
.statuspill.mute{background:color-mix(in srgb,var(--border) 60%,transparent);color:var(--sub)}
[data-theme="dark"] .statuspill.ok,[data-theme="dark"] .exv{color:#34D399}
[data-theme="dark"] .statuspill.warn,[data-theme="dark"] .exv.warn{color:#FBBF24}
[data-theme="dark"] .statuspill.err{color:#F87171}
[data-theme="dark"] .statuspill.b{color:#60A5FA}

/* 빠른 입력 «새 경비» 패널 — 머리 «경비 추가» 버튼·N 으로 표 카드 위에 펼친다(2026-09-25 입구 하나로 통일) */
.exq-hbtn kbd{font:inherit;font-size:var(--fs-xs);font-weight:var(--w-bold);opacity:.8;border:1px solid rgba(255,255,255,.45);
  border-radius:var(--r-xs);padding:0 var(--s-2);margin-left:var(--s-3);line-height:1.5}
.exq{padding:var(--s-9) var(--s-10) var(--s-8);border-bottom:1px solid var(--border);
  background:linear-gradient(180deg,color-mix(in srgb,var(--accent) 5%,var(--card)),var(--card));animation:exqIn var(--d-3) var(--ease)}
@keyframes exqIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}
.exq[hidden]{display:none}
.exq-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--s-7)}
.exq-title{display:flex;align-items:center;gap:var(--s-4);font-size:var(--fs-lg);font-weight:var(--w-black)}
.exq-dot{width:8px;height:8px;border-radius:50%;background:var(--accent)}
.exq-cats{display:flex;flex-wrap:wrap;gap:var(--s-3);margin-bottom:var(--s-7)}
.exq-cats label{position:relative;display:inline-flex;align-items:center;gap:var(--s-3);cursor:pointer;
  border:1px solid var(--border);background:var(--card);color:var(--sub);border-radius:var(--r-pill);
  padding:var(--s-3) var(--s-7) var(--s-3) var(--s-5);font-size:var(--fs-sm);font-weight:var(--w-bold);transition:var(--d-1) var(--ease)}
.exq-cats label svg{width:15px;height:15px;stroke-width:2;color:var(--c)}
.exq-cats label:hover{color:var(--text)}
.exq-cats input{position:absolute;opacity:0;pointer-events:none}
.exq-cats label:has(input:checked){border-color:var(--c);color:var(--text);background:color-mix(in srgb,var(--c) 10%,var(--card))}
.exq-cats label:has(input:focus-visible){outline:2px solid var(--c);outline-offset:2px}
.exq-grid{display:grid;gap:var(--s-5);align-items:end;
  grid-template-columns:150px minmax(200px,2.2fr) minmax(140px,1.3fr) 150px auto}
.exq-f{display:flex;flex-direction:column;gap:var(--s-3);min-width:0}
.exq-f>span{font-size:var(--fs-xs);font-weight:var(--w-bold);color:var(--sub)}
.exq-f input{height:44px;padding:0 var(--s-6);border:1px solid var(--border);border-radius:var(--r-md);background:var(--card);
  color:var(--text);font-family:inherit;font-size:var(--fs-md);width:100%;box-shadow:0 1px 2px rgba(16,24,40,.04)}
.exq-f input:focus{outline:2px solid var(--accent);border-color:transparent}
.exq-f input::placeholder{color:var(--sub)}
.exq-amt{position:relative}
.exq-amt input{text-align:right;padding-right:var(--s-16);font-weight:var(--w-bold);font-variant-numeric:tabular-nums}
.exq-amt>em{position:absolute;right:var(--s-6);bottom:0;height:44px;display:flex;align-items:center;
  color:var(--sub);font-size:var(--fs-sm);font-style:normal;pointer-events:none}
.exm .exq-amt>em{height:40px}
.exq-add{height:44px;padding:0 var(--s-12);justify-content:center}
.exq-x{width:34px;height:34px;border:0;background:none;border-radius:var(--r-md);color:var(--sub);cursor:pointer;display:grid;place-items:center}
.exq-x svg{width:17px;height:17px}
.exq-x:hover{background:var(--bg);color:var(--text)}
.exq .exl{margin-top:var(--s-7)}
.exq .exl-lbl{min-width:52px;font-size:var(--fs-xs)}
.exq-foot{display:flex;align-items:center;justify-content:space-between;gap:var(--s-6);flex-wrap:wrap;margin-top:var(--s-8);
  padding-top:var(--s-6);border-top:1px dashed var(--border);font-size:var(--fs-sm)}
.exq-done{display:inline-flex;align-items:center;gap:var(--s-3);color:#059669;font-weight:var(--w-bold)}
.exq-done[hidden]{display:none}
.exq-done svg{width:15px;height:15px}
.exq-keys{color:var(--sub);margin-left:auto}
.exq-keys kbd{font:inherit;font-size:var(--fs-xs);font-weight:var(--w-bold);border:1px solid var(--border);border-bottom-width:2px;
  border-radius:var(--r-xs);padding:0 var(--s-2);background:var(--card);margin:0 var(--s-1)}
[data-theme="dark"] .exq-done{color:#34D399}
/* 방금 넣은 행 — 잠깐 칠했다가 사라진다 */
.tabulator-row.exq-new{animation:exqFlash 2.4s var(--ease)}
@keyframes exqFlash{0%,35%{background:color-mix(in srgb,var(--accent) 14%,transparent)}100%{background:transparent}}
@media (prefers-reduced-motion:reduce){.tabulator-row.exq-new{animation:none;background:color-mix(in srgb,var(--accent) 8%,transparent)}}

/* 표 셀 */
.exd{font-variant-numeric:tabular-nums;color:var(--sub);white-space:nowrap}
.exd b{color:var(--text);font-weight:var(--w-bold)}
/* 올해 연도는 화면에서만 숨긴다 — 글자는 남겨 정렬이 해를 넘어도 맞게 */
.exd-y.cur{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.exc{display:inline-flex;align-items:center;gap:var(--s-5);font-weight:var(--w-semibold);color:var(--text)}
.exc .wg-ic{width:28px;height:28px;border-radius:var(--r-md);background:color-mix(in srgb,var(--c) 13%,transparent);color:var(--c)}
.exc .wg-ic svg{width:16px;height:16px}
.exct{min-width:0;max-width:100%;overflow:hidden}
.exrcw{display:inline-flex;align-items:center;gap:var(--s-3)}
/* 관리자 «직원별 경비» 처리 칸 · 경비 관리 → 직원 링크 (2026-09-25) */
.exact{display:inline-flex;align-items:center;gap:var(--s-3);white-space:nowrap}
.exact form{display:inline}
.exm-who{color:inherit;text-decoration:none;border-bottom:1px dashed color-mix(in srgb,var(--sub) 50%,transparent)}
.exm-who:hover{color:var(--accent-t);border-bottom-color:var(--accent)}
.page-sub .link{color:var(--accent-t);text-decoration:none;font-weight:var(--w-semibold)}
.ext{font-weight:var(--w-bold);color:var(--text);line-height:1.35;white-space:normal}
.exr{font-size:var(--fs-sm);color:var(--sub);margin-top:var(--s-1);max-width:420px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.exa{font-weight:var(--w-black);font-variant-numeric:tabular-nums;white-space:nowrap}
.exa small{font-size:var(--fs-xs);font-weight:var(--w-semibold);color:var(--sub);margin-left:var(--s-1)}
.exrc{display:inline-flex;align-items:center;gap:var(--s-3);border:1px solid var(--border);background:var(--card);
  border-radius:var(--r-pill);padding:var(--s-2) var(--s-6);font:inherit;font-size:var(--fs-sm);font-weight:var(--w-bold);
  color:var(--text);cursor:pointer;white-space:nowrap;transition:var(--d-1) var(--ease);min-height:24px}
.exrc svg{width:14px;height:14px;stroke-width:2.2}
.exrc:hover{border-color:var(--accent);color:var(--accent-t)}
.exrc.off{cursor:default;color:var(--sub)}
.exrc.off:hover{border-color:var(--border);color:var(--sub)}
.exrc.need{border-color:transparent;background:var(--accent-weak);color:var(--accent-t)}
.exrc.need:hover{background:var(--accent);color:#fff}
.exv{font-size:var(--fs-xs);font-weight:var(--w-bold);color:var(--ok-t)}
.exv.warn{color:var(--warn-t)}.exv.err{color:var(--err-t)}.exv.mute{color:var(--sub)}
/* 모바일 카드(gwCardList)에 들어간 분류 칸은 작게 */
.gcard-code .exc{font-size:var(--fs-sm);gap:var(--s-3)}
.gcard-code .exc .wg-ic{width:22px;height:22px;border-radius:var(--r-sm)}
.gcard-code .exc .wg-ic svg{width:13px;height:13px}
.gcard-right .exa{font-size:var(--fs-md)}
.gcard .exr{max-width:none;white-space:normal}

/* 신청 모달 — 폰에선 아래에서 올라오는 시트 */
.exm .field{margin-top:var(--s-7)}
.exm .field input,.exm .field textarea{font-size:var(--fs-md)}
.exm .exq-cats{margin:var(--s-6) 0 0}
.exm-2{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-5)}
.exm .exq-amt input{padding-right:var(--s-16)}
.exsheet-grab{display:none}
@media (max-width:768px){
  .exh{padding:var(--s-9)}
  .exh-nav{order:-1;width:100%;justify-content:space-between}
  .exq{padding:var(--s-7)}
  /* 폰: 날짜·금액을 한 줄에, 내용·비고·버튼은 통째 한 줄씩 */
  /* 폰은 머리 버튼이 아래 시트를 연다 — 패널이 열려도(N 등) 날짜·금액 한 줄, 나머지는 통째 한 줄씩 */
  .exq-grid{grid-template-columns:1fr 1fr}
  .exq-grid .c-content,.exq-grid .c-reason,.exq-add{grid-column:1 / -1}
  .exq-keys,.exq-hbtn kbd{display:none}
  .modal-bg.exsheet{align-items:flex-end;padding:0}
  .modal-bg.exsheet .modal{width:100%;max-width:100%;border-radius:var(--r-xl) var(--r-xl) 0 0;
    padding:var(--s-4) var(--s-10) calc(var(--s-10) + env(safe-area-inset-bottom));max-height:92vh;overflow-y:auto;
    animation:sheetup var(--d-3) var(--spring)}
  .exsheet-grab{display:block;width:44px;height:5px;border-radius:var(--r-xs);background:var(--border);margin:var(--s-2) auto var(--s-7);cursor:pointer}
  .modal-bg.exsheet .modal-actions .btn{flex:1;height:46px;justify-content:center}
}

/* ===== 경비 사용처 연결 (2026-09-25) — 추천 칩·검색 창·목록 표시·상세 «관련 경비» ===== */
.exl{display:flex;align-items:flex-start;gap:var(--s-5);margin-top:var(--s-6)}
.exl-lbl{flex:none;font-size:var(--fs-sm);font-weight:var(--w-bold);color:var(--sub);padding-top:var(--s-3);min-width:40px}
.exl-chips{display:flex;flex-wrap:wrap;gap:var(--s-3);align-items:center;min-width:0}
.exl-chip{display:inline-flex;align-items:center;gap:var(--s-3);max-width:320px;border:1px solid var(--border);background:var(--card);
  color:var(--sub);border-radius:var(--r-pill);padding:var(--s-3) var(--s-6);font:inherit;font-size:var(--fs-sm);font-weight:var(--w-semibold);
  cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:var(--d-1) var(--ease)}
.exl-chip b{font-weight:var(--w-bold);color:var(--text)}
.exl-chip:hover{color:var(--text)}
.exl-chip.hot{border-color:color-mix(in srgb,var(--accent) 45%,var(--border))}
.exl-chip.on{border-color:var(--accent);background:var(--accent-weak);color:var(--accent-t)}
.exl-chip.on b{color:var(--accent-t)}
.exl-more{display:inline-flex;align-items:center;gap:var(--s-2);border:0;background:none;color:var(--accent-t);font:inherit;
  font-size:var(--fs-sm);font-weight:var(--w-bold);cursor:pointer;padding:var(--s-3) var(--s-2)}
.exl-more svg{width:13px;height:13px}
.exl-none{font-size:var(--fs-sm);color:var(--sub)}
.exm .exl{margin-top:var(--s-7)}
/* 목록 — 내용 아래 한 줄 */
.exl-line{display:flex;align-items:center;flex-wrap:wrap;gap:var(--s-3);margin-top:var(--s-2)}
.exl-line:empty{display:none}
.exl-tag{display:inline-flex;align-items:center;gap:var(--s-3);max-width:360px;font-size:var(--fs-xs);font-weight:var(--w-semibold);
  color:var(--text);text-decoration:none;background:var(--bg);border-radius:var(--r-xs);padding:var(--s-1) var(--s-4);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.exl-tag b{color:var(--accent-t);font-weight:var(--w-bold)}
.exl-tag:hover{background:var(--accent-weak)}
.exl-edit{display:inline-flex;align-items:center;gap:var(--s-2);border:0;background:none;padding:var(--s-1) var(--s-2);font:inherit;
  font-size:var(--fs-xs);font-weight:var(--w-bold);color:var(--sub);cursor:pointer;border-radius:var(--r-xs);min-height:24px}
.exl-edit svg{width:12px;height:12px}
.exl-edit:hover{opacity:1;color:var(--accent-t);background:var(--accent-weak)}
@media (hover:hover){ .tabulator-row:not(:hover) .exl-edit{opacity:0} .exl-tag + .exl-edit{opacity:.75} }
/* 검색·선택 창 */
.exl-pick .modal{width:min(520px,100%)}
.exl-q{width:100%;height:42px;padding:0 var(--s-6);border:1px solid var(--border);border-radius:var(--r-md);background:var(--card);
  color:var(--text);font-family:inherit;font-size:var(--fs-md);margin-top:var(--s-3)}
.exl-q:focus{outline:2px solid var(--accent);border-color:transparent}
.exl-list{margin-top:var(--s-5);max-height:46vh;overflow-y:auto;border:1px solid var(--border);border-radius:var(--r-lg);display:flex;flex-direction:column}
.exl-row{display:grid;grid-template-columns:auto 1fr;gap:var(--s-1) var(--s-5);text-align:left;padding:var(--s-6) var(--s-7);border:0;
  border-bottom:1px solid var(--border);background:var(--card);color:var(--text);font:inherit;cursor:pointer;transition:background var(--d-1) var(--ease)}
.exl-row:last-child{border-bottom:0}
.exl-row:hover,.exl-row.on{background:var(--accent-weak)}
.exl-k{grid-row:1 / span 2;align-self:center;font-size:var(--fs-xs);font-weight:var(--w-bold);color:var(--accent-t);background:var(--accent-weak);
  border-radius:var(--r-xs);padding:var(--s-1) var(--s-4)}
.exl-t{font-weight:var(--w-bold);font-size:var(--fs-md);line-height:1.35}
.exl-m{font-size:var(--fs-sm);color:var(--sub)}
.exl-empty{padding:var(--s-10) var(--s-8);text-align:center;color:var(--sub);font-size:var(--fs-base)}
/* 상세 «관련 경비» */
.exrel{padding:var(--s-9) var(--s-10);margin-bottom:var(--s-6)}
.exrel-head{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s-5);flex-wrap:wrap}
.exrel-head .card-title{margin:0}
.exrel-sum{font-size:var(--fs-base);color:var(--sub);font-variant-numeric:tabular-nums}
.exrel-sum b{font-size:var(--fs-lg);font-weight:var(--w-black);color:var(--text)}
.exrel-list{margin-top:var(--s-6);display:flex;flex-direction:column}
.exrel-row{display:grid;grid-template-columns:52px 1fr auto;gap:var(--s-6);align-items:center;padding:var(--s-5) 0;border-top:1px solid color-mix(in srgb,var(--border) 60%,transparent)}
.exrel-d{font-size:var(--fs-sm);color:var(--sub);font-variant-numeric:tabular-nums}
.exrel-c{display:flex;flex-direction:column;min-width:0}
.exrel-t{font-weight:var(--w-bold);font-size:var(--fs-base);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.exrel-m{font-size:var(--fs-sm);color:var(--sub)}
.exrel-a{font-weight:var(--w-black);font-variant-numeric:tabular-nums;white-space:nowrap}
.exrel-a small{font-size:var(--fs-xs);font-weight:var(--w-semibold);color:var(--sub);margin-left:var(--s-1)}
.exrel-row.dead{opacity:.5}
.exrel-row.dead .exrel-a{text-decoration:line-through}
.exrel-empty{margin:var(--s-5) 0 0;font-size:var(--fs-base)}
@media (max-width:768px){
  /* 세로 배치에선 칩 줄이 폭을 꽉 채워야 긴 칩이 말줄임된다(안 그러면 시트 밖으로 잘려 나갔다) */
  .exl{flex-direction:column;align-items:stretch;gap:var(--s-3)}
  .exl-lbl{padding-top:0}
  .exl-chips{width:100%}
  .exl-chip{max-width:100%}
  .exrel{padding:var(--s-8)}
}

/* 재호출(추가근무) 종료 미확인 — 근태 탭 입력 줄(2026-09-25) */
.att-reclose{border-left:3px solid var(--accent)}
.att-reclose form{display:flex;align-items:center;gap:var(--s-5);flex-wrap:wrap}
.att-reclose input[type=time]{height:36px;padding:0 var(--s-5);border:1px solid var(--border);border-radius:var(--r-md);background:var(--card);color:var(--text);font-family:inherit}
.att-reclose .btn{padding:var(--s-3) var(--s-8)}
.badge.muted{background:transparent}  /* 기본 배지 바탕(주황 틴트) 위 회색 글자 4.36 → 중립 바탕 */

/* 근태 정정 승인 — 판단 재료 카드(2026-09-27) */
.cor-sum{display:flex;flex-wrap:wrap;gap:var(--s-6) var(--s-12);padding:var(--s-7) var(--s-9);margin-bottom:var(--s-4)}
.cor-sum-k{font-size:var(--fs-xs);color:var(--sub);font-weight:var(--w-semibold)}
.cor-sum-v{font-size:var(--fs-lg);font-weight:var(--w-bold);font-variant-numeric:tabular-nums}
.cor-guide{margin:0 0 var(--s-8)}
.cor-month{font-size:var(--fs-md);font-weight:var(--w-bold);margin:var(--s-10) 0 var(--s-4)}
.cor-month span{font-size:var(--fs-sm);font-weight:var(--w-normal);color:var(--sub);margin-left:var(--s-3)}
.cor-card{padding:var(--s-8) var(--s-9);margin-bottom:var(--s-5)}
.cor-top{display:flex;justify-content:space-between;align-items:center;gap:var(--s-4);flex-wrap:wrap}
.cor-who b{font-size:var(--fs-md)}
.cor-who span{color:var(--sub);margin-left:var(--s-2)}
.cor-time{display:flex;align-items:center;flex-wrap:wrap;gap:var(--s-3);margin-top:var(--s-5);font-variant-numeric:tabular-nums}
.cor-cur{color:var(--sub)}
.cor-cur em{font-style:normal;font-size:var(--fs-xs);margin-left:var(--s-2)}
.cor-arrow{color:var(--sub)}
.cor-req{font-weight:var(--w-bold);color:var(--text)}
.cor-add{font-size:var(--fs-sm);font-weight:var(--w-bold);color:var(--accent-t)}
.cor-meta{margin:var(--s-5) 0 0;display:grid;gap:var(--s-2)}
.cor-meta>div{display:flex;gap:var(--s-5);font-size:var(--fs-sm)}
.cor-meta dt{flex:0 0 64px;color:var(--sub)}
.cor-meta dd{margin:0;min-width:0}
.cor-foot{display:flex;justify-content:space-between;align-items:center;gap:var(--s-4);flex-wrap:wrap;margin-top:var(--s-6)}
.cor-wait{font-size:var(--fs-xs);color:var(--sub)}
.cor-btns{display:flex;gap:var(--s-3)}
.cor-btns .btn{padding:var(--s-3) var(--s-7)}
.cor-rej{color:var(--err-t)}
.cor-grade.ok{color:var(--ok-t)}.cor-grade.warn{color:var(--warn-t)}.cor-grade.err{color:var(--err-t)}.cor-grade.mute{color:var(--sub)}
/* ♿ 키보드·폰 접근성 (2026-09-27 디자인 전수조사) */
/* ① 닫힌 드로어는 화면 밖으로 밀려만 있어 Tab 이 안으로 들어갔다(포커스가 «사라짐», 11화면).
   닫힘 애니메이션이 끝난 뒤(visibility 지연) 숨겨 탭 순서에서 뺀다. 열릴 땐 즉시 보인다. */
.drawer{visibility:hidden;transition:transform var(--d-3) var(--spring,var(--ease)),visibility 0s linear var(--d-3)}
.drawer-bg.open .drawer{visibility:visible;transition:transform var(--d-3) var(--spring,var(--ease)),visibility 0s}
/* ② 폰: 키보드로 옮긴 포커스가 하단 탭바·상단 앱바에 가렸다(26화면) — 스크롤 여백을 예약 */
@media (max-width:767px){ html{scroll-padding-top:var(--s-32);scroll-padding-bottom:calc(var(--s-32) + var(--s-6) + env(safe-area-inset-bottom))} }
/* ③ 포커스 표시가 없던 부품 — 표 스크롤 영역·할일 체크·즐겨찾기·Vault 검색 */
.tabulator .tabulator-tableholder:focus-visible,button.td-check:focus-visible,.cs-star:focus-visible,
.vlt-search input:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:var(--r-sm)}
/* ④ 표의 숫자는 자릿수 폭을 고정(열이 흔들리지 않게) */
.tabulator .tabulator-cell,.num,td.num{font-variant-numeric:tabular-nums}

/* 근태 — 오늘 카드 안 상태 버튼 구역(2026-09-27 두 카드 합침) */
.att-merge{border-top:1px solid var(--hair);margin-top:var(--s-8);padding-top:var(--s-7)}

/* 경비 표(PC) — 마우스를 올려야 보이는 «업무 연결» 버튼이 줄마다 24px 자리를 차지해 표가 비어 보였다(2026-09-27).
   연결된 업무가 없는 줄에선 자리를 없애고 제목 오른쪽 위에 겹쳐 띄운다. 폰(hover 없음)은 그대로. */
@media (hover:hover){
  .tabulator-row .tabulator-cell:has(.exct){position:relative}
  .tabulator-row .exl-line:not(:has(.exl-tag)){margin:0;height:0}
  .tabulator-row .exl-line:not(:has(.exl-tag)) .exl-edit{position:absolute;top:50%;right:var(--s-4);transform:translateY(-50%);background:var(--card)}
}

/* 🧩 유틸(2026-09-27 인라인 style 정리 1차) — 템플릿에 손으로 반복되던 한 줄 style 을 이름으로.
   인라인 style 은 클래스 규칙보다 셌다 → 같은 결과를 내려고 !important. 새 코드도 한 줄짜리는 이걸 쓴다. */
.fs-sm{font-size:var(--fs-sm)!important}.fs-base{font-size:var(--fs-base)!important}
.fw-b{font-weight:var(--w-bold)!important}.fw-n{font-weight:var(--w-normal)!important}
.m0{margin:0!important}.mb4{margin-bottom:var(--s-4)!important}.mt5{margin-top:var(--s-5)!important}.mt6{margin-top:var(--s-6)!important}
.d-inline{display:inline!important}.c-accent{color:var(--accent-t)!important}
.pad-xs{padding:var(--s-2) var(--s-6)!important}.pad-xsn{padding:var(--s-2) var(--s-5)!important}
/* 🧩 유틸 2차(2026-09-27) — 토큰 이름 그대로: mtN/mbN/gapN=var(--s-N) · pA-B=padding var(--s-A) var(--s-B) · fs-(크기) · fw-(굵기) · c-(글자색 토큰). 인라인과 같은 결과를 위해 !important.
   🚨 JS/Alpine 이 같은 속성을 바꾸는 요소(id·x-show·:style)엔 쓰지 말 것 — 인라인 변경이 안 먹는다. */
.ai-c{align-items:center!important}
.bc-err{border-color:var(--err)!important}
.c-err{color:var(--err-t)!important}
.c-inherit{color:inherit!important}
.c-ok{color:var(--ok-t)!important}
.c-sub{color:var(--sub)!important}
.c-text{color:var(--text)!important}
.c-warn{color:var(--warn-t)!important}
.cur-p{cursor:pointer!important}
.d-flex{display:flex!important}
.f1{flex:1!important}
.fs-lg{font-size:var(--fs-lg)!important}
.fs-md{font-size:var(--fs-md)!important}
.fs-xs{font-size:var(--fs-xs)!important}
.fw-bk{font-weight:var(--w-black)!important}
.fw-md{font-weight:var(--w-medium)!important}
.fw-sb{font-weight:var(--w-semibold)!important}
.gap6{gap:var(--s-6)!important}
.jc-sb{justify-content:space-between!important}
.mb2{margin-bottom:var(--s-2)!important}
.mb3{margin-bottom:var(--s-3)!important}
.mb5{margin-bottom:var(--s-5)!important}
.mb6{margin-bottom:var(--s-6)!important}
.mb7{margin-bottom:var(--s-7)!important}
.mb8{margin-bottom:var(--s-8)!important}
.minw0{min-width:0!important}
.mt1{margin-top:var(--s-1)!important}
.mt10{margin-top:var(--s-10)!important}
.mt12{margin-top:var(--s-12)!important}
.mt2{margin-top:var(--s-2)!important}
.mt3{margin-top:var(--s-3)!important}
.mt4{margin-top:var(--s-4)!important}
.mt7{margin-top:var(--s-7)!important}
.mt8{margin-top:var(--s-8)!important}
.nowrap{white-space:nowrap!important}
.ox-auto{overflow-x:auto!important}
.p10{padding:var(--s-10)!important}
.p12{padding:var(--s-12)!important}
.p16{padding:var(--s-16)!important}
.p2-3{padding:var(--s-2) var(--s-3)!important}
.p2-5{padding:var(--s-2) var(--s-5)!important}
.p2-6{padding:var(--s-2) var(--s-6)!important}
.p24{padding:var(--s-24)!important}
.p3-1{padding:var(--s-3) var(--s-1)!important}
.p3-5{padding:var(--s-3) var(--s-5)!important}
.p3-6{padding:var(--s-3) var(--s-6)!important}
.p3-7{padding:var(--s-3) var(--s-7)!important}
.p3-8{padding:var(--s-3) var(--s-8)!important}
.p3-9{padding:var(--s-3) var(--s-9)!important}
.p4-10{padding:var(--s-4) var(--s-10)!important}
.p4-6{padding:var(--s-4) var(--s-6)!important}
.p4-7{padding:var(--s-4) var(--s-7)!important}
.p4-8{padding:var(--s-4) var(--s-8)!important}
.p4-9{padding:var(--s-4) var(--s-9)!important}
.p5-1{padding:var(--s-5) var(--s-1)!important}
.p5-12{padding:var(--s-5) var(--s-12)!important}
.p5-8{padding:var(--s-5) var(--s-8)!important}
.p6{padding:var(--s-6)!important}
.p6-9{padding:var(--s-6) var(--s-9)!important}
.p7{padding:var(--s-7)!important}
.p7-10{padding:var(--s-7) var(--s-10)!important}
.p7-8{padding:var(--s-7) var(--s-8)!important}
.p7-9{padding:var(--s-7) var(--s-9)!important}
.p8{padding:var(--s-8)!important}
.p8-8{padding:var(--s-8) var(--s-8)!important}
.p8-9{padding:var(--s-8) var(--s-9)!important}
.p9-10{padding:var(--s-9) var(--s-10)!important}
.pos-rel{position:relative!important}
.shrink0{flex-shrink:0!important}
.ta-c{text-align:center!important}
.ta-r{text-align:right!important}
.td-none{text-decoration:none!important}

/* ── 시스템 흐름도(2026-10-06, templates/manage_system_map.html · static/js/sysmap.js) ── */
#smap{--kc:var(--sub)}   /* 종류 색 — 상자마다 스크립트가 덮어쓴다 */
#smap [hidden]{display:none!important}   /* .smap-empty 의 display:flex 가 hidden 을 덮던 것 */
.smap-bar{display:flex;align-items:center;gap:var(--s-5);flex-wrap:wrap;margin-bottom:var(--s-6)}
.smap-bar .seg-tabs{margin-right:auto}
.smap-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,3fr);gap:var(--s-6);align-items:start}
.smap-side{display:flex;flex-direction:column;gap:var(--s-4);position:sticky;top:var(--s-6);max-height:calc(100vh - 140px);overflow:hidden}
.smap-q{width:100%;padding:var(--s-4) var(--s-5);border:1px solid var(--border);border-radius:var(--r-md);background:var(--card);color:var(--text);font:inherit;font-size:var(--fs-sm)}
.smap-kinds{display:flex;flex-wrap:wrap;gap:var(--s-2)}
.smap-chip{all:unset;cursor:pointer;display:inline-flex;align-items:center;gap:var(--s-2);padding:var(--s-1) var(--s-4);border:1px solid var(--border);border-radius:var(--r-pill);font-size:var(--fs-xs);color:var(--sub)}
.smap-chip i,.smap-item i{display:inline-block;width:8px;height:8px;border-radius:var(--r-pill);flex:none}
.smap-chip span{color:var(--sub);opacity:.7}
.smap-chip.on{border-color:var(--accent);color:var(--text);background:color-mix(in srgb,var(--accent) 8%,var(--card))}
.smap-list{overflow:auto;display:flex;flex-direction:column;gap:var(--s-1);min-height:0}
.smap-item{all:unset;cursor:pointer;display:flex;align-items:center;gap:var(--s-3);padding:var(--s-3) var(--s-4);border-radius:var(--r-sm);font-size:var(--fs-sm)}
.smap-item:hover{background:var(--bg)}
.smap-item.on{background:color-mix(in srgb,var(--accent) 10%,var(--card));font-weight:var(--w-bold)}
.smap-item .smap-l{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.smap-deg{font-size:var(--fs-micro);color:var(--sub)}
.smap-stage{min-height:420px;position:relative}
.smap-empty{display:flex;flex-direction:column;gap:var(--s-3)}
.smap-hubs{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:var(--s-4);margin-top:var(--s-5)}
.smap-canvas{position:relative;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr) minmax(0,1fr);gap:var(--s-16);align-items:start}
.smap-svg{position:absolute;inset:0;pointer-events:none;overflow:visible}
.smap-svg path{fill:none;stroke-width:1.5;opacity:.45}
.smap-col{display:flex;flex-direction:column;gap:var(--s-3);position:relative;z-index:1;min-width:0}
.smap-mid{align-self:start}
.smap-colh{font-size:var(--fs-xs);color:var(--sub);font-weight:var(--w-semibold);margin-bottom:var(--s-1)}
.smap-cell{display:flex;flex-direction:column;gap:var(--s-1)}
.smap-el{font-size:var(--fs-micro);color:var(--sub);padding-left:var(--s-3)}
.smap-node{all:unset;cursor:pointer;box-sizing:border-box;display:flex;flex-direction:column;gap:var(--s-1);width:100%;padding:var(--s-4) var(--s-5);background:var(--card);border:1px solid var(--border);border-left:3px solid var(--kc);border-radius:var(--r-md);transition:box-shadow var(--d-1),border-color var(--d-1)}
.smap-node:hover{box-shadow:0 2px 10px rgba(0,0,0,.06);border-color:color-mix(in srgb,var(--kc) 45%,var(--border))}
.smap-node .smap-l{font-size:var(--fs-sm);font-weight:var(--w-bold);color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.smap-node .smap-s{font-size:var(--fs-micro);color:var(--sub);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.smap-k{font-size:var(--fs-micro);font-weight:var(--w-semibold);color:var(--kc)}
.smap-focus{border:2px solid var(--kc);box-shadow:0 4px 18px color-mix(in srgb,var(--kc) 22%,transparent)}
.smap-focus .smap-l{white-space:normal}
.smap-detail{margin-top:var(--s-10);padding-top:var(--s-8);border-top:1px solid var(--border)}
.smap-dh{display:flex;align-items:baseline;gap:var(--s-4);font-size:var(--fs-base)}
.smap-kvs{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:var(--s-4) var(--s-8);margin-top:var(--s-5)}
.smap-kv{display:flex;flex-direction:column;gap:var(--s-1);min-width:0}
.smap-kv span{font-size:var(--fs-micro);color:var(--sub)}
.smap-kv b{font-size:var(--fs-sm);font-weight:var(--w-semibold);word-break:break-all}
.smap-links{margin-top:var(--s-5);font-size:var(--fs-sm)}
.smap-sum{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:var(--s-5);margin-bottom:var(--s-6)}
.smap-go{all:unset;cursor:pointer;color:var(--text);font-weight:var(--w-semibold)}
.smap-go:hover{color:var(--accent-t);text-decoration:underline}
@media (max-width:900px){
  .smap-grid{grid-template-columns:minmax(0,1fr)}
  .smap-side{position:static;max-height:none}
  .smap-list{max-height:280px}
  .smap-canvas{grid-template-columns:minmax(0,1fr);gap:var(--s-8)}
  .smap-mid{position:static;order:-1}
}
