/* ===========================================================
   G Reward 디자인 시스템
   레퍼런스: 한국 금융앱 (흰 배경 · 큰 숫자 · 테두리 대신 여백)

   ⚠️ 이 파일 밖에서 px 값을 직접 쓰지 마라.
      크기·간격·라운드는 아래 스케일 토큰에서만 가져온다.
      규칙은 docs/DESIGN.md 에 정리되어 있다.
   =========================================================== */

:root{
  /* ---- 색: 먹 ---- */
  --ink:#14181f;      /* 본문·숫자 */
  --ink-2:#5a6472;    /* 보조 텍스트 */
  --ink-3:#98a1ae;    /* 라벨·캡션 */

  /* ---- 색: 바탕 ---- */
  --bg:#fff;          /* 기본 */
  --bg-2:#f3f5f8;     /* 블록 바탕 */
  --bg-3:#e8ecf2;     /* 눌린 면·트랙 */
  --line:#eaeef3;     /* 구분선 */

  /* ---- 색: 액센트 ---- */
  --brand:#1d4ed8;
  --brand-ink:#1741b6;
  --brand-bg:#edf2ff;

  /* ---- 색: 의미 ---- */
  --up:#e0342a;       /* 상승·플러스 (한국식) */
  --warn:#b45309;   --warn-bg:#fdf4e7;
  --bad:#c0392f;    --bad-bg:#fdefed;
  --ok:#0f7a4f;     --ok-bg:#e9f6ef;

  /* ---- 색: 어두운 면 ---- */
  --dark:#141a24;
  --on-dark:#c9d2df;
  --on-dark-2:#8793a4;

  /* ==== 타입 스케일 — 반쪽 사이즈(13.5 같은 것) 금지 ==== */
  --fs-2xs:11px;   /* 태그·다리표시 */
  --fs-xs:12px;    /* 라벨·캡션 */
  --fs-sm:13px;    /* 보조 설명·표 본문 */
  --fs-md:14px;    /* 버튼·폼 라벨 */
  --fs-base:15px;  /* 본문 */
  --fs-lg:17px;    /* 섹션 제목 */
  --fs-xl:20px;    /* 강조 숫자 */
  --fs-2xl:24px;   /* 페이지 제목 */
  --fs-3xl:30px;   /* 로그인 제목 */
  --fs-display:clamp(36px,9vw,46px);  /* 히어로 금액 */

  /* 글자 굵기 — 400/500/600/700/800 만 */
  --fw-normal:400; --fw-medium:500; --fw-semi:600; --fw-bold:700; --fw-black:800;

  /* 자간 — 클수록 타이트하게 */
  --ls-display:-.045em;
  --ls-title:-.035em;
  --ls-num:-.03em;
  --ls-base:-.01em;

  /* 행간 */
  --lh-tight:1.2;   /* 큰 숫자·제목 */
  --lh-snug:1.45;   /* 중간 */
  --lh-base:1.6;    /* 본문 */

  /* ==== 간격 — 4px 그리드 ==== */
  --s0:2px;   /* hairline gap 예외 */
  --s1:4px;
  --s2:8px;
  --s3:12px;
  --s4:16px;
  --s5:20px;
  --s6:24px;
  --s8:32px;
  --s10:40px;
  --s12:48px;

  /* ==== 라운드 ==== */
  --r-sm:8px;     /* 버튼·입력·작은 블록 */
  --r-md:12px;    /* 트리 노드·중간 블록 */
  --r-lg:18px;    /* 큰 블록·카드 */
  --r-full:999px; /* 칩·바 */

  /* ==== 그림자 — 2단계만 ==== */
  --sh-1:0 1px 2px rgba(20,24,31,.07);
  --sh-2:0 -1px 0 var(--line),0 -6px 20px rgba(20,24,31,.05);

  /* ==== 모션 — 지속시간 4개 · 이징 3개 ====
     ⚠️ 여기 없는 값을 화면 코드에서 만들지 마라. 화면마다 속도가 달라지면
        같은 시스템으로 안 보인다. 색 토큰과 같은 취급이다. */
  --t-fast:140ms;    /* 눌림·호버·색 변화 */
  --t-base:260ms;    /* 표시자 이동·펼침·접힘 */
  --t-slow:520ms;    /* 형태 변형(morph)·카드 전환 */
  --t-story:1600ms;  /* 진행률처럼 '기다림을 보여주는' 구간 */
  --e-out:cubic-bezier(.22,1,.36,1);       /* 기본 — 빠르게 나가 천천히 멈춘다 */
  --e-spring:cubic-bezier(.34,1.56,.64,1); /* 등장 — 살짝 넘어갔다 돌아온다 */
  --e-inout:cubic-bezier(.65,0,.35,1);     /* 왕복 */

  /* ==== 레이아웃 상수 ==== */
  --side-w:216px;
  --main-max:1080px;
  /* ⚠️ 실제 하단바 높이와 같아야 한다. 이 값으로 본문 아래 여백과 상담
     단추 높이를 잡기 때문에, 2px 만 어긋나도 단추가 하단바에 걸린다.
     구성: 위아래 padding(--s2 ×2 = 16) + 단추(--s3 ×2 + 아이콘 24 = 48). */
  --tabbar-h:64px;
  /* 카카오 상담 단추 높이 — 위아래 안쪽 여백(--s3) + 아이콘 20px.
     본문이 이 단추에 깔리지 않도록 main 아래 여백을 잴 때 쓴다. */
  --support-h:44px;

  --font:"Pretendard Variable",Pretendard,-apple-system,BlinkMacSystemFont,
         "Apple SD Gothic Neo","Malgun Gothic",system-ui,sans-serif;
  --mono:ui-monospace,SFMono-Regular,Menlo,monospace;

  /* ==== 면 위에 얹히는 것들 (다크에서 방향이 뒤집힌다) ==== */
  --field:var(--bg);    /* --bg-2 면 위의 입력란 */
  --seg-on:var(--bg);   /* 세그먼트 활성 */
  --node:var(--bg);     /* 조직도 노드 */
  /* 조직도 연결선. ⚠️ `--bg-3` 을 쓰지 마라 — 조직도 바탕이 `--bg-2` 라
     둘의 대비가 거의 없어서 선이 있어도 안 보인다. 실제로 그랬다. */
  --tree-line:#9aa6b4;
}

/* ===========================================================
   테마 — 라이트가 기본. html[data-theme] 로 강제하고,
   'system' 일 때만 OS 설정을 따른다. (app.js 의 테마 토글이 세팅)
   =========================================================== */
:root[data-theme="dark"] {
    --ink:#e8ecf2; --ink-2:#a2acba; --ink-3:#6f7987;
    --bg:#12151a; --bg-2:#1a1f27; --bg-3:#242b35; --line:#222932;
    --brand:#6690ff; --brand-ink:#88a8ff; --brand-bg:#1a2340;
    --up:#ff6b5e;
    --warn:#e0a45c; --warn-bg:#2c2214;
    --bad:#ef8278; --bad-bg:#2e1a18;
    --ok:#4bbd88; --ok-bg:#132a1f;
    --dark:#0d1015; --on-dark:#c9d2df; --on-dark-2:#7d8797;
    --sh-1:none;
    --sh-2:0 -1px 0 var(--line);
    /* 면 위에 얹히는 것들 — 라이트에서는 더 밝게, 다크에서는 더 밝게 (방향이 반대다) */
    --field:var(--bg-3); --seg-on:var(--bg-3); --node:var(--bg-3);
    --tree-line:#46515f;
}
@media (prefers-color-scheme:dark) {
  :root[data-theme="system"] {
    --ink:#e8ecf2; --ink-2:#a2acba; --ink-3:#6f7987;
    --bg:#12151a; --bg-2:#1a1f27; --bg-3:#242b35; --line:#222932;
    --brand:#6690ff; --brand-ink:#88a8ff; --brand-bg:#1a2340;
    --up:#ff6b5e;
    --warn:#e0a45c; --warn-bg:#2c2214;
    --bad:#ef8278; --bad-bg:#2e1a18;
    --ok:#4bbd88; --ok-bg:#132a1f;
    --dark:#0d1015; --on-dark:#c9d2df; --on-dark-2:#7d8797;
    --sh-1:none;
    --sh-2:0 -1px 0 var(--line);
    /* 면 위에 얹히는 것들 — 라이트에서는 더 밝게, 다크에서는 더 밝게 (방향이 반대다) */
    --field:var(--bg-3); --seg-on:var(--bg-3); --node:var(--bg-3);
    --tree-line:#46515f;
  }
}

/* ===========================================================
   기본
   =========================================================== */
*{box-sizing:border-box}
html,body{height:100%}
body{
  margin:0;background:var(--bg);color:var(--ink);font-family:var(--font);
  font-size:var(--fs-base);line-height:var(--lh-base);letter-spacing:var(--ls-base);
  -webkit-font-smoothing:antialiased;
}
/* 숫자는 전부 폭 고정 */
.n,.big,.v,td.n,th.n{font-variant-numeric:tabular-nums}

.shell{display:flex;min-height:100%}
.hide{display:none !important}

/* ===========================================================
   타이포 — 이 5개가 전부다
   h1 페이지 제목 / h2 섹션 제목 / lede 페이지 설명 / note 보조 / 본문
   =========================================================== */
h1{font-size:var(--fs-2xl);font-weight:var(--fw-bold);letter-spacing:var(--ls-title);
   line-height:var(--lh-tight);margin:0 0 var(--s1)}
h2{font-size:var(--fs-lg);font-weight:var(--fw-bold);letter-spacing:var(--ls-num);
   line-height:var(--lh-snug);margin:0 0 var(--s3)}
h3{font-size:var(--fs-md);font-weight:var(--fw-semi);letter-spacing:var(--ls-base);
   margin:0 0 var(--s2)}
p.lede{font-size:var(--fs-md);color:var(--ink-2);margin:0 0 var(--s6);max-width:66ch}
p.note{font-size:var(--fs-sm);color:var(--ink-3);margin:0 0 var(--s3);max-width:70ch;
       line-height:var(--lh-snug)}
p.note:last-child{margin-bottom:0}

/* 섹션 = 제목 + 내용 한 덩어리. 섹션 사이는 항상 --s8 */
.sec{margin-bottom:var(--s8)}
.sechd{display:flex;justify-content:space-between;align-items:baseline;
       margin-bottom:var(--s3);gap:var(--s3)}
.sechd h2{margin:0}

/* 카드 머리 = 제목 + 오른쪽에 그 카드의 행동 하나. 제목과 단추를 같은 줄에 둔다 */
.cardhd{display:flex;justify-content:space-between;align-items:center;
        gap:var(--s3);flex-wrap:wrap}
.cardhd h3{margin:0}
.sechd span{font-size:var(--fs-xs);color:var(--ink-3)}
main > section > h2{margin-top:var(--s8)}
main > section > h2:first-child{margin-top:0}

.row{display:flex;gap:var(--s2);align-items:center;margin:var(--s3) 0;flex-wrap:wrap}
.grid2{display:grid;grid-template-columns:repeat(auto-fit,minmax(290px,1fr));gap:var(--s2)}

/* ===========================================================
   사이드 (PC)
   =========================================================== */
.side{width:var(--side-w);flex:none;background:var(--dark);color:var(--on-dark);
      display:flex;flex-direction:column;padding:var(--s6) 0 var(--s5)}
.brand{display:flex;gap:var(--s2);align-items:center;padding:0 var(--s5) var(--s6)}
/*
 * 브랜드 심볼 — `web/shared/brand-symbol.svg` 와 **같은 그림**이다.
 * ⚠️ 글자 "G" 로 되돌리지 마라. 글꼴이 없는 기기에서 모양이 달라지고,
 *    심볼과 파비콘과 로고가 각각 다른 G 가 된다.
 * ⚠️ 색은 그라데이션이 제 안에 들고 있다. `fill` 을 밖에서 덮어쓰지 마라 —
 *    덮어쓰면 평평한 한 색이 되어 입체감이 사라진다.
 */
.brand .mark{width:28px;height:28px;flex:none;display:block}
/*
 * 로그인 화면의 전체 로고 — 심볼 + 가운뎃점 + 워드마크 + imgp®.
 * ⚠️ 글자는 `currentColor` 다. 색을 박지 마라 — 라이트·다크에서 각각
 *    읽히려면 글자색을 따라가야 한다. 심볼의 그라데이션과 imgp 의 앰버는
 *    제 안에 들고 있다.
 */
/* ⚠️ `color` 를 박지 마라. 로그인 카드는 밝고 사이드바는 어둡다 —
      글자를 흰색으로 고정하면 카드 위에서 통째로 사라진다(실제로 그랬다). */
.loginlogo{display:block;height:38px;width:auto;margin:0 auto var(--s5)}
.brand strong{display:block;font-size:var(--fs-lg);font-weight:var(--fw-bold);color:#fff;
              letter-spacing:var(--ls-num);line-height:var(--lh-tight)}
.brand em{font-style:normal;font-size:var(--fs-2xs);color:var(--on-dark-2)}

.top{display:flex;align-items:center;gap:var(--s2);padding:0 var(--s5) var(--s5)}
.who{font-size:var(--fs-xs);color:var(--on-dark-2);line-height:var(--lh-snug);
     min-width:0;flex:1;overflow:hidden}
.who b,.who span{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.who b{color:#fff;font-size:var(--fs-md);font-weight:var(--fw-semi)}
.logout{background:none;border:1px solid rgba(255,255,255,.16);color:var(--on-dark-2);
        font-size:var(--fs-2xs);padding:var(--s1) var(--s2);border-radius:var(--r-sm);
        cursor:pointer;font-family:var(--font);white-space:nowrap;flex:none}
.logout:hover{color:#fff;border-color:rgba(255,255,255,.35)}

.side nav{display:flex;flex-direction:column;gap:var(--s0);padding:0 var(--s3)}
.side nav button{background:none;border:0;color:var(--on-dark-2);font-family:var(--font);
                 font-size:var(--fs-md);font-weight:var(--fw-medium);text-align:left;
                 padding:var(--s2) var(--s3);border-radius:var(--r-sm);cursor:pointer;
                 letter-spacing:var(--ls-base)}
.side nav button:hover{color:#fff;background:rgba(255,255,255,.05)}
.side nav button.on{color:#fff;background:var(--brand);font-weight:var(--fw-semi)}
/* 활성 배경이 점프하지 않고 미끄러진다. 배경색이 아니라 뒤에 깔린 알약이 움직인다.
   위치는 transform 으로만 옮긴다 — top 을 애니메이션하면 매 프레임 레이아웃이 다시 계산된다. */
.side nav{position:relative}
.side nav .navind{position:absolute;left:0;right:0;top:0;height:0;z-index:0;
  background:var(--brand);border-radius:var(--r-sm);opacity:0;
  transition:transform var(--t-base) var(--e-out),height var(--t-base) var(--e-out),
             opacity var(--t-base) var(--e-out)}
.side nav button{position:relative;z-index:1;
  transition:color var(--t-base) var(--e-out)}
/* 알약이 생기면 버튼 자신의 배경은 지운다 — 두 겹으로 보이면 안 된다 */
.side nav.hasind button.on{background:transparent}
.sidefoot{margin-top:auto;padding:var(--s5) var(--s5) 0;font-size:var(--fs-2xs);
          color:var(--on-dark-2);line-height:1.7;border-top:1px solid rgba(255,255,255,.07)}

/*
 * 표와 조직도가 주인인 화면은 폭 상한을 푼다(`data-wide`).
 *
 * `--main-max` 는 **긴 글이 한 줄에 너무 길어지지 않게** 두는 값인데,
 * 조직도·회원목록·출금목록처럼 넓을수록 잘 읽히는 화면에서는 오른쪽이
 * 통째로 흰 여백으로 남는다. 조직도는 가로로 잘려 끌어야 하는데 옆에
 * 빈 자리가 남아 있었다.
 *
 * ⚠️ 글까지 같이 늘어나지는 않는다 — `p.lede`(66ch)·`p.note`(70ch)가 제
 *    폭을 들고 있다. 새 설명 문단을 만들 때 그 둘을 쓰지 않으면 와이드
 *    화면에서 한 줄이 150자가 된다.
 * ⚠️ `:has()` 를 모르는 옛 브라우저는 그냥 지금처럼 1080px 로 남는다.
 *    기능이 아니라 여백 이야기라 그래도 된다.
 */
main:has(> section.on[data-wide]){max-width:none}

main{flex:1;min-width:0;max-width:var(--main-max);
     /* 아래 여백은 눈금이 아니라 부품 높이에서 나온다 — 오른쪽 아래에 떠 있는
        카카오 상담 단추(--s5 만큼 띄움 + --support-h)를 본문이 피해야 한다. */
     padding:var(--s8) var(--s8) calc(var(--s5) + var(--support-h) + var(--s3))}
section{display:none}
section.on{display:block}

/* ===========================================================
   폼
   =========================================================== */
input,select{
  font-family:var(--font);font-size:var(--fs-base);color:var(--ink);background:var(--bg-2);
  border:0;border-radius:var(--r-sm);padding:var(--s3);width:100%;margin-top:var(--s1);
}
input::placeholder{color:var(--ink-3)}
.card input,.card select,.step input,.step select{background:var(--field)}
input:focus,select:focus{outline:2px solid var(--brand);outline-offset:0}
label{display:block;font-size:var(--fs-sm);color:var(--ink-2);margin-bottom:var(--s3);
      font-weight:var(--fw-medium)}
.row label{margin:0;display:flex;gap:var(--s2);align-items:center}
/* ⚠️ 안에 늘어나는 입력칸(찾아 고르는 칸)이 들어가는 라벨에만 준다.
   min-width:0 이 없으면 min-content 가 20글자쯤이라 좁은 화면에서 페이지가
   통째로 옆으로 스크롤된다. 모든 라벨에 주면 짧은 라벨이 찌그러진다. */
.row label.grow{min-width:0;flex:1 1 220px}
/* 입력이 flex 로 늘어나면 라벨 글자가 한 자씩 세로로 접힌다 */
.row label > span{white-space:nowrap;flex:none}
.row input,.row select{width:auto;margin:0;padding:var(--s2) var(--s3);font-size:var(--fs-md)}

.btn{font-family:var(--font);font-size:var(--fs-md);font-weight:var(--fw-semi);
     color:var(--ink);background:var(--bg-2);border:0;border-radius:var(--r-sm);
     padding:var(--s3) var(--s4);cursor:pointer;white-space:nowrap;letter-spacing:var(--ls-base)}
.btn:hover{background:var(--bg-3)}
.btn.primary{background:var(--brand);color:#fff}
.btn.primary:hover{background:var(--brand-ink)}
.btn.danger{color:var(--bad);background:var(--bad-bg)}
.btn:disabled{opacity:.4;cursor:not-allowed}
.btn.sm{padding:var(--s1) var(--s3);font-size:var(--fs-xs);font-weight:var(--fw-medium)}
.btn.block{width:100%;padding:var(--s4);font-size:var(--fs-lg)}

/* ===========================================================
   제출 버튼 상태기계 — lib.js 의 submit() 이 data-state 를 움직인다.
   버튼을 숨기고 스피너를 띄우지 않는다. **버튼 자신이** 채워진다.
   누른 자리에서 결과가 나오므로 눈이 화면을 헤매지 않는다.
   =========================================================== */
.btn[data-state]{position:relative;overflow:hidden;isolation:isolate;
  transition:background var(--t-slow) var(--e-out),color var(--t-slow) var(--e-out)}
/* 채워지는 면. 요청이 언제 끝날지 모르므로 90% 까지만 가고 멈춘다 —
   100% 를 찍어 놓고 기다리게 하면 그게 거짓말이다. */
.btn[data-state]::after{content:"";position:absolute;inset:0;z-index:-1;
  background:rgba(255,255,255,.22);transform:scaleX(0);transform-origin:left}
.btn:not(.primary)[data-state]::after{background:rgba(29,78,216,.14)}
.btn[data-state="run"]::after{transform:scaleX(.9);
  transition:transform var(--t-story) var(--e-out)}
.btn[data-state="done"]::after{transform:scaleX(1);
  transition:transform var(--t-fast) linear}
/* 진행 중에는 잠기지만 흐려지지 않는다 — 흐려지면 '안 눌렸나' 로 읽힌다.
   실제 잠금은 submit() 의 가드다. 이건 마우스까지 막아 두는 것. */
.btn[data-state="run"],.btn[data-state="done"]{pointer-events:none}
.btn[data-state="run"]{cursor:progress}
.btn[data-state="run"]:disabled,.btn[data-state="done"]:disabled{opacity:1}
.btn[data-state="done"]{background:var(--ok);color:#fff}
.btn[data-state="done"]:hover{background:var(--ok)}
/* 완료 면에는 막을 씌우지 않는다 — primary 와 일반 버튼의 초록이 달라 보인다 */
.btn[data-state="done"]::after{background:transparent}

/* ⚠️ 마진을 정하지 않으면 `<p>` 는 브라우저 기본 `1em` 을 쓴다. 글씨가
   13px 이라 마진도 13px — 눈금에 없는 값이 화면 여기저기에 생긴다. */
.msg{font-size:var(--fs-sm);color:var(--ink-3);margin:var(--s3) 0 0}
.msg.ok{color:var(--ok)} .msg.no{color:var(--bad)}

/*
 * ⚠️ **접히게 둔다.** 고르는 값이 늘면(출금 상태가 넷 → 여섯) 좁은 화면에서
 *    페이지가 통째로 가로로 넘친다 — 360px 에서 123px 이 밀려 나갔다.
 *    탭 하나를 감추거나 잘라내면 그 상태를 고를 길이 사라지므로 줄을 바꾼다.
 */
.seg{display:inline-flex;flex-wrap:wrap;gap:var(--s0);max-width:100%;
     background:var(--bg-2);border-radius:var(--r-sm);padding:var(--s0)}
.seg button{background:none;border:0;font-family:var(--font);font-size:var(--fs-sm);
            font-weight:var(--fw-medium);color:var(--ink-2);padding:var(--s2) var(--s4);
            cursor:pointer;border-radius:6px;letter-spacing:var(--ls-base)}
.seg button.on{background:var(--seg-on);color:var(--ink);font-weight:var(--fw-semi);box-shadow:var(--sh-1)}


/* ===========================================================
   로그인
   =========================================================== */
/* ⚠️ 인증 화면은 라이트/다크와 무관하게 **항상 어둡다.**
      토큰을 쓰지 않고 색을 직접 박는 유일한 자리다 — 두 테마에서 같은 얼굴이어야 하고,
      데이터가 없는 화면이라 대비를 깎아도 잃을 게 없다.
      유리(backdrop-filter)를 여기 말고 다른 데 쓰지 마라: 정산 표에 씌우면
      숫자 대비가 무너지고 수백 행 스크롤이 무거워진다. (docs/DESIGN.md §5-1) */
.login{min-height:100dvh;display:flex;align-items:center;justify-content:center;
       padding-block:var(--s8);padding-inline:var(--s5);position:relative;isolation:isolate;
       background:var(--ground);color:var(--card-ink)}

.login .box{width:100%;max-width:380px;
  padding:var(--s8) var(--s6);border-radius:var(--r-lg);
  background:var(--surface);border:1px solid var(--hair);box-shadow:var(--glow);
  animation:boxIn var(--t-slow) var(--e-out) backwards}
@keyframes boxIn{from{opacity:0;transform:translateY(14px) scale(.985)}}

.login h1{font-size:var(--fs-3xl);letter-spacing:var(--ls-display);margin-bottom:var(--s1);
          color:#fff}
.login .sub{font-size:var(--fs-md);color:#9aa4b8;margin:0 0 var(--s8)}
.login label{margin-bottom:var(--s4);color:#9aa4b8}
/* 입력란은 반투명으로 두지 않는다 — 비밀번호를 치는 자리라 대비가 최우선이다 */
.login input{background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.14);
             color:#fff;transition:border-color var(--t-base),box-shadow var(--t-base)}
.login input::placeholder{color:#6d7788}
.login input:focus{border-color:var(--accent-2);box-shadow:0 0 0 3px rgba(232,163,61,.24);outline:none}
.login .btn{width:100%;padding:var(--s4);font-size:var(--fs-lg);margin-top:var(--s2)}
.login .btn.primary{box-shadow:0 10px 28px rgba(232,163,61,.34)}
.login .msg{margin-top:var(--s3)}
.login .hint{margin-top:var(--s6);padding:var(--s4);background:rgba(255,255,255,.045);
             border-radius:var(--r-sm);font-size:var(--fs-xs);color:#8b95a7;line-height:1.75}
.login .hint b{color:#c4ccda;font-weight:var(--fw-semi)}

/* ===========================================================
   마이오피스 홈
   =========================================================== */
.greet{margin-bottom:var(--s6)}
.greet h1{margin-bottom:var(--s2)}
.greet .tags{display:flex;flex-wrap:wrap;gap:var(--s1)}
.tagpill{font-size:var(--fs-xs);font-weight:var(--fw-semi);padding:var(--s1) var(--s3);
         border-radius:var(--r-full);background:var(--bg-2);color:var(--ink-2)}
.tagpill.b{background:var(--brand-bg);color:var(--brand)}
.tagpill.g{background:var(--warn-bg);color:var(--warn)}

.amount{padding:0 0 var(--s6)}
.amount .lab{font-size:var(--fs-md);color:var(--ink-2);font-weight:var(--fw-medium)}
.amount .big{font-size:var(--fs-display);font-weight:var(--fw-black);
             letter-spacing:var(--ls-display);line-height:var(--lh-tight);margin:var(--s1) 0 0}
.amount .big small{font-size:.42em;font-weight:var(--fw-bold);margin-left:var(--s0);
                   letter-spacing:var(--ls-num)}
.amount .delta{font-size:var(--fs-md);color:var(--ink-3);margin-top:var(--s2)}
.amount .delta b{color:var(--up);font-weight:var(--fw-semi)}

.trio{display:grid;grid-template-columns:repeat(3,1fr);background:var(--bg-2);
      border-radius:var(--r-lg);padding:var(--s4) var(--s1);margin-bottom:var(--s2)}
.trio > div{text-align:center;padding:0 var(--s2);position:relative}
.trio > div + div::before{content:'';position:absolute;left:0;top:12%;height:76%;
                          width:1px;background:var(--bg-3)}
.trio .k{font-size:var(--fs-xs);color:var(--ink-3);display:block;margin-bottom:var(--s1)}
.trio .v{font-size:var(--fs-lg);font-weight:var(--fw-bold);letter-spacing:var(--ls-num);
         font-variant-numeric:tabular-nums}

.prog{background:var(--bg-2);border-radius:var(--r-lg);padding:var(--s4);margin-bottom:var(--s8)}
.prog .hd{display:flex;justify-content:space-between;align-items:baseline;gap:var(--s3);
          font-size:var(--fs-sm);color:var(--ink-2);margin-bottom:var(--s3)}
.prog .hd b{font-weight:var(--fw-bold);color:var(--ink);letter-spacing:var(--ls-num);
            font-variant-numeric:tabular-nums}
.prog .track{height:var(--s2);background:var(--bg-3);border-radius:var(--r-full);overflow:hidden}
.prog .track i{display:block;height:100%;background:var(--brand);border-radius:var(--r-full);
               transition:width .45s cubic-bezier(.4,0,.2,1)}
.prog.warn .track i{background:var(--warn)}
.prog.full .track i{background:var(--bad)}

.advice{background:var(--brand-bg);border-radius:var(--r-lg);padding:var(--s4);
        margin-bottom:var(--s4)}
.advice .t{font-size:var(--fs-base);font-weight:var(--fw-bold);color:var(--brand);
           letter-spacing:var(--ls-num);margin-bottom:var(--s1)}
.advice .d{font-size:var(--fs-sm);color:var(--ink-2);line-height:var(--lh-snug)}
.advice.flat{background:var(--bg-2)}
.advice.flat .t{color:var(--ink)}

.legs{display:flex;justify-content:space-between;align-items:flex-end;
      margin-bottom:var(--s3);gap:var(--s3)}
.legs .one{min-width:0}
.legs .one.r{text-align:right}
.legs .k{font-size:var(--fs-xs);color:var(--ink-3)}
.legs .v{font-size:var(--fs-xl);font-weight:var(--fw-bold);letter-spacing:var(--ls-num);
         line-height:var(--lh-tight);font-variant-numeric:tabular-nums}
.legs .s{font-size:var(--fs-xs);color:var(--ink-3);margin-top:var(--s0)}
.legs .one.weak .v{color:var(--warn)}
/*
 * 다리 숫자 밑 설명 — 큰 숫자가 「남은 실적」 이라는 걸 말해 주는 줄이다.
 * ⚠️ 빼지 마라. 짝이 지어지면 양쪽에서 같이 빠져서 다 쓴 다리가 0 으로
 *    보이는데, 회원은 그걸 "내 실적이 안 잡혔다" 로 읽는다 — 문의가 왔다.
 */
.legs + p.note{font-size:var(--fs-2xs);line-height:var(--lh-base);
               color:var(--ink-3);margin:calc(-1 * var(--s1)) 0 var(--s3);max-width:none}
.seesaw{display:grid;grid-template-columns:1fr 1fr;gap:var(--s0);height:var(--s2)}
.seesaw i{background:var(--bg-3);border-radius:var(--r-full);position:relative;overflow:hidden}
.seesaw i span{position:absolute;top:0;bottom:0;background:var(--brand);
               border-radius:var(--r-full);transition:width .45s cubic-bezier(.4,0,.2,1)}
.seesaw i.l span{right:0}
.seesaw i.r span{left:0}
.seesaw i.weak span{background:var(--warn)}

/* 리스트 — 카드가 아니다 */
.list{background:var(--bg-2);border-radius:var(--r-lg);overflow:hidden}
.list .li{display:flex;justify-content:space-between;align-items:center;gap:var(--s3);
          padding:var(--s3) var(--s4);font-size:var(--fs-md);min-height:48px}
.list .li + .li{box-shadow:inset 0 1px 0 var(--bg-3)}
.list .li .k{color:var(--ink-2)}
.list .li .v{font-weight:var(--fw-bold);letter-spacing:var(--ls-num);
             font-variant-numeric:tabular-nums}
.list .li .v small{font-weight:var(--fw-medium);color:var(--ink-3);
                   font-size:var(--fs-sm);margin-left:var(--s0)}

.quick{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s2)}
.quick button{display:flex;flex-direction:column;align-items:center;gap:var(--s2);
              background:var(--bg-2);border:0;border-radius:var(--r-lg);
              padding:var(--s4) var(--s2);cursor:pointer;font-family:var(--font);
              font-size:var(--fs-xs);font-weight:var(--fw-semi);color:var(--ink);
              letter-spacing:var(--ls-base)}
.quick button:hover{background:var(--bg-3)}
.quick svg{width:22px;height:22px;stroke:var(--brand);fill:none;stroke-width:1.8;
           stroke-linecap:round;stroke-linejoin:round}

/* ===========================================================
   데이터 블록 (관리자 포함)
   =========================================================== */
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(168px,1fr));gap:1px;
       background:transparent;border-radius:var(--r-lg);overflow:hidden}
.stat{background:var(--bg);padding:var(--s4);box-shadow:0 0 0 1px var(--line)}
.stat .k{font-size:var(--fs-xs);color:var(--ink-3);display:block;margin-bottom:var(--s0)}
/* ⚠️ `nowrap` 은 값이 숫자일 때 얘기다. "실서비스 모드" 같은 글자 값이
   들어오면 칸을 뚫고 나간다 — 768px 에서 실제로 그랬다. 넘칠 때만 접는다. */
.stat .v{font-size:var(--fs-xl);font-weight:var(--fw-bold);letter-spacing:var(--ls-num);
         font-variant-numeric:tabular-nums;overflow-wrap:break-word}
.stat .k{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.stat .u{font-size:var(--fs-sm);color:var(--ink-3);margin-left:var(--s0);font-weight:var(--fw-medium)}

.kv{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:1px;
    background:transparent;border-radius:var(--r-lg);overflow:hidden}
.kv div{background:var(--bg);padding:var(--s3) var(--s4);box-shadow:0 0 0 1px var(--line)}
.kv .k{font-size:var(--fs-xs);color:var(--ink-3);display:block}
.kv .v{font-size:var(--fs-md);font-weight:var(--fw-semi);letter-spacing:var(--ls-base)}

.card{background:var(--bg-2);border-radius:var(--r-lg);padding:var(--s4)}
/* ── 장(章)의 세로 리듬 ──────────────────────────────────────
 *
 * ⚠️ **간격의 주인은 장이지 부품이 아니다.** 이 규칙을 지우고 부품마다
 *    `margin-bottom` 을 들려 보내지 마라 — 그게 원래 방식이었고, 그래서
 *    같은 화면 안에서 12px(`.tw`)·20px(`.card`)·8px(`.bar`)이 규칙 없이
 *    섞였다. 무엇이 오느냐에 따라 간격이 달라지니 사람 눈에는 "제각각" 이다.
 *    부품은 자기가 어디에 놓일지 모른다. 아는 것은 장뿐이다.
 *
 * 리듬은 셋이고, 셋에는 각각 이유가 있다:
 *    32px  새 제목 앞    — 새 이야기가 시작된다
 *    12px  제목 바로 뒤  — 제목과 그 내용은 한 덩어리다
 *    20px  그 밖의 사이  — 덩어리와 덩어리
 *
 * ⚠️ 바로 밑 자식의 `margin-bottom` 을 0 으로 내리는 줄을 빼지 마라.
 *    안 내리면 부품이 들고 온 아래 여백에 이 규칙의 위 여백이 **더해져서**
 *    같은 종류인데도 자리마다 다른 값이 된다.
 * ⚠️ 장 **바로 밑**에만 건다. 카드 안쪽은 부품이 제 간격을 그대로 쓴다.
 * ⚠️ 격자(`.stats`·`.trio`)는 `gap` 이 맡으므로 건드리지 않는다.
 */
.subpane.on > *,
section[data-pane] > *,
.stack.stack > *,
.sec.sec > *{margin-bottom:0}
.subpane.on > * + *,
section[data-pane] > * + *,
.stack.stack > * + *,
.sec.sec > * + *{margin-top:var(--s5)}
.subpane.on > * + :is(h2,h3),
section[data-pane] > * + :is(h2,h3),
.stack.stack > * + :is(h2,h3),
.sec.sec > * + :is(h2,h3){margin-top:var(--s8)}
.subpane.on > :is(h2,h3) + *,
section[data-pane] > :is(h2,h3) + *,
.stack.stack > :is(h2,h3) + *,
.sec.sec > :is(h2,h3) + *{margin-top:var(--s3)}
.subpane.on > h2 + h3,
section[data-pane] > h2 + h3,
.stack.stack > h2 + h3,
.sec.sec > h2 + h3{margin-top:var(--s5)}
/* 한 줄짜리 안내가 여럿 이어질 때는 서로 붙여 한 덩어리로 읽히게 한다 */
.subpane.on > .note + .note,
section[data-pane] > .note + .note,
.stack.stack > .note + .note,
.sec.sec > .note + .note{margin-top:var(--s2)}
/*
 * `.stack` — 속이 비친 포장지에 리듬을 물려준다.
 *
 * ⚠️ 카드를 여러 장 담는 `<div>` 를 만들면 **반드시 `.stack` 을 붙여라.**
 *    장의 리듬은 장 **바로 밑**까지만 닿는다. 포장지 하나만 끼워도 그
 *    안쪽은 간격이 0 이 되어 카드가 벽처럼 맞닿는다 — 회원 상세
 *    (`#mdBody`)가 실제로 0px 이었고, 그 화면만 보면 어디가 한 카드인지
 *    알 수 없었다.
 * ⚠️ 배경·테두리가 있는 상자(`.card`)에는 붙이지 마라. 그건 포장지가
 *    아니라 덩어리 자체이고, 안쪽 간격은 그 부품들이 정한다.
 *
 * ⚠️ `.stack.stack` / `.sec.sec` 처럼 클래스를 두 번 적은 것은 오타가 아니다.
 *    **컨테이너가 부품이 제 몸에 지닌 여백을 반드시 이겨야 한다.** 한 번만
 *    적으면 우선순위가 같아서 파일 뒤쪽에 있는 부품 규칙(`.more`,
 *    `.guard` …)이 이기고, 리듬은 그 부품이 있는 자리에서만 조용히 깨진다.
 *    파일 순서에 기대는 방법(이 블록을 맨 뒤로 옮기기)은 다음 사람이
 *    그 뒤에 한 줄을 더하는 순간 무너진다.
 */
.card.accent{background:var(--brand-bg)}

.bar{display:flex;height:var(--s10);border-radius:var(--r-sm);overflow:hidden;
     margin-bottom:var(--s2)}
.bar div{display:flex;align-items:center;justify-content:center;font-size:var(--fs-xs);
         font-weight:var(--fw-semi);color:#fff;min-width:0;overflow:hidden;white-space:nowrap}
.barkey{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s5);font-size:var(--fs-xs);
        color:var(--ink-3)}
/* 좁은 화면에서 막대 안 라벨이 안 보일 때만 쓰는 범례 */
.barlegend{display:none;flex-wrap:wrap;gap:var(--s1) var(--s4);font-size:var(--fs-xs);
           color:var(--ink-2);margin-bottom:var(--s2)}
.barlegend > span{display:inline-flex;align-items:center;gap:var(--s1)}
.barlegend i{width:10px;height:10px;border-radius:3px;flex:none}

/* 표 */
.tw{overflow-x:auto;border-radius:var(--r-lg);background:var(--bg-2);margin-bottom:var(--s3)}
table{border-collapse:collapse;width:100%;min-width:420px;font-size:var(--fs-sm)}
th,td{padding:var(--s3) var(--s4);text-align:left}
thead th{font-weight:var(--fw-medium);font-size:var(--fs-xs);color:var(--ink-3);
         white-space:nowrap;padding:var(--s4) var(--s4) var(--s1)}
tbody td{box-shadow:inset 0 1px 0 var(--bg-3)}
td.n,th.n{text-align:right;white-space:nowrap}
/*
 * 남는 가로 공간은 **`.fill` 을 단 칸**이 먹는다.
 *
 * 표가 창 끝까지 넓어지면서 남는 폭이 가운데 아무 칸에나 몰렸다 — 출금
 * 목록에서 `검토자` 와 `신청일` 사이가 벌어졌다. 한 칸을 고무줄로 정해
 * 두면 빈 자리는 늘 그 칸에 모인다.
 *
 * ⚠️ **맨 끝 칸(`:last-child`)에 일괄로 걸지 마라.** 그러면 나머지 칸이
 *    전부 min-content 까지 쫄아들고, 한글은 min-content 가 **한 글자**라
 *    `판매원패키지` 가 세로로 한 줄씩 쌓인다. 거래 내역에서 실제로 그랬다.
 * ⚠️ 한 표에 하나만 달아라. 둘이면 둘이 나눠 가져 다시 가운데가 벌어진다.
 * ⚠️ `table-layout:fixed` 로 바꾸지 마라. `#`·금액 칸까지 똑같이 나뉘어
 *    번호 한 자리에 100px 이 가고 이름이 잘린다.
 */
tbody tr:hover td{background:var(--bg-3)}
code{font-family:var(--mono);font-size:.88em;background:var(--bg-3);
     padding:1px var(--s1);border-radius:5px;letter-spacing:0}

/* 목록 도구줄 안의 체크박스 한 줄 */
.chkline{display:inline-flex;align-items:center;gap:var(--s2);margin:0;
         font-size:var(--fs-xs);color:var(--ink-2);white-space:nowrap}
.chkline input{margin:0}

.tag{display:inline-block;font-size:var(--fs-2xs);font-weight:var(--fw-semi);
     padding:var(--s0) var(--s2);border-radius:var(--r-full)}
.tag.ok{background:var(--ok-bg);color:var(--ok)}
.tag.no{background:var(--bad-bg);color:var(--bad)}
.tag.mut{background:var(--bg-3);color:var(--ink-3)}
.tag.acc{background:var(--brand-bg);color:var(--brand)}
/* 인정코드(044) — 매출 없이 수당이 나가는 계정. 정상도 오류도 아니라
   **눈에 걸려야 하는** 상태다. 탈퇴(no)·휴면(mut)과 색이 갈려야 한다. */
.tag.warn{background:var(--warn-bg);color:var(--warn)}

/* 점검 결과는 수십 줄짜리 촘촘한 목록이다 — 장의 리듬(20px)으로 띄우면
   한 화면에 몇 줄 안 들어온다. **그래서 일부러 좁힌다**: 간격을 목록이
   `gap` 으로 직접 들고 있으면 검사도 "의도한 것" 으로 읽는다.
   ⚠️ `--s1`(4px)로 되돌리지 마라. 이 앱의 어느 리듬에도 없는 값이라
      촘촘한 목록이 아니라 "붙어서 잘못 그려진 것" 으로 읽힌다. */
#guards{display:flex;flex-direction:column;gap:var(--s2)}
.guard{display:flex;gap:var(--s3);align-items:flex-start;background:var(--bg-2);
       border-radius:var(--r-sm);padding:var(--s3) var(--s4)}
.guard.fail{background:var(--bad-bg)}
/* 제목 첫 줄에 눈높이를 맞춘다. app.js 안에 style="margin-top:3px" 으로
   박혀 있던 걸 눈금 값으로 옮겼다 — 날 px 은 이 파일 밖에 두지 않는다. */
.guard > .tag{margin-top:var(--s0);flex:none}
.guard .body{min-width:0}
.guard .title{font-weight:var(--fw-semi);font-size:var(--fs-md)}
.guard .desc{font-size:var(--fs-xs);color:var(--ink-3)}
.guard .m{font-family:var(--mono);font-size:var(--fs-2xs);color:var(--ink-3);
          margin-top:var(--s1);word-break:break-all;letter-spacing:0}

/* ===========================================================
   내역 행 (.rows) — 표 대신 쓰는 금융앱 거래내역 문법
   좁은 화면에서 7컬럼 표는 읽을 수 없다. 2줄 구조로 둔다.
   =========================================================== */
.rows{background:var(--bg-2);border-radius:var(--r-lg);overflow:hidden}
.rows .r{display:flex;justify-content:space-between;align-items:flex-start;
         gap:var(--s3);padding:var(--s3) var(--s4)}
.rows .r + .r{box-shadow:inset 0 1px 0 var(--bg-3)}
.rows .r > div{min-width:0}
.rows .r > div:last-child{text-align:right;flex:none}
.rows .t{font-size:var(--fs-md);font-weight:var(--fw-semi);letter-spacing:var(--ls-base);
         overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rows .t.num{font-weight:var(--fw-bold);letter-spacing:var(--ls-num);
             font-variant-numeric:tabular-nums}
.rows .t.minus{color:var(--bad)}
.amount .big.minus{color:var(--bad)}
.rows .s{font-size:var(--fs-xs);color:var(--ink-3);margin-top:var(--s0);
         display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap}
.rows .r > div:last-child .s{justify-content:flex-end}

/* 알림 한 줄 — 안 읽은 것은 왼쪽에 표시가 붙는다 */
.noti{background:var(--bg-2);border-radius:var(--r-lg);overflow:hidden}
.noti .n{display:flex;gap:var(--s3);padding:var(--s3) var(--s4);align-items:flex-start;
         box-shadow:inset 0 1px 0 var(--bg-3)}
.noti .n:first-child{box-shadow:none}
.noti .n.new{background:var(--brand-bg)}
.noti .ic{width:30px;height:30px;border-radius:var(--r-full);flex:none;display:grid;
          place-items:center;background:var(--bg-3);color:var(--ink-3);
          font-size:var(--fs-2xs);font-weight:var(--fw-bold)}
.noti .n.new .ic{background:var(--brand);color:#fff}
.noti .b{min-width:0;flex:1}
.noti .t{font-size:var(--fs-md);font-weight:var(--fw-medium);line-height:var(--lh-snug)}
.noti .d{font-size:var(--fs-xs);color:var(--ink-3);margin-top:var(--s0)}

/* 빈 상태 */
.empty{background:var(--bg-2);border-radius:var(--r-lg);padding:var(--s8) var(--s5);
       text-align:center}
.empty .t{font-size:var(--fs-md);font-weight:var(--fw-semi);margin-bottom:var(--s1)}
.empty .d{font-size:var(--fs-sm);color:var(--ink-3);line-height:var(--lh-snug);
          max-width:44ch;margin:0 auto}

/* 단계 표시 (회원 추천) */
.steps{display:flex;flex-direction:column;gap:var(--s3)}
.step{background:var(--bg-2);border-radius:var(--r-lg);padding:var(--s4)}
.step .hd{display:flex;align-items:center;gap:var(--s2);margin-bottom:var(--s3)}
.step .no{width:22px;height:22px;border-radius:var(--r-full);background:var(--bg-3);
          color:var(--ink-3);font-size:var(--fs-xs);font-weight:var(--fw-bold);
          display:grid;place-items:center;flex:none}
.step.done .no,.step.now .no{background:var(--brand);color:#fff}
.step .hd h3{margin:0;font-size:var(--fs-md)}
.step label{margin-bottom:var(--s2)}
.step label:last-of-type{margin-bottom:0}

/* 자리 추천 배지 */
.slot.rec{box-shadow:inset 0 0 0 1px var(--brand);color:var(--brand)}
.slot b{font-weight:var(--fw-bold)}
.slot .sub{opacity:.55;font-weight:var(--fw-medium)}
.slot .why{font-weight:var(--fw-bold);margin-left:var(--s1)}
.slotgrp{margin-bottom:var(--s3)}
.slotgrp:last-child{margin-bottom:0}
.slotgrp .lb{font-size:var(--fs-xs);color:var(--ink-3);margin-bottom:var(--s2);
             display:flex;gap:var(--s2);align-items:center}
.slotgrp .lb b{color:var(--brand);font-weight:var(--fw-semi)}

/* 조직도 요약 바 */
.orgsum{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s2);
         margin-bottom:var(--s3)}
.orgsum > div{background:var(--bg-2);border-radius:var(--r-sm);
              padding:var(--s3) var(--s4);min-width:0}
.orgsum .k{font-size:var(--fs-xs);color:var(--ink-3);display:block}
.orgsum .v{font-size:var(--fs-md);font-weight:var(--fw-bold);letter-spacing:var(--ls-num);
           font-variant-numeric:tabular-nums;white-space:nowrap;
           overflow:hidden;text-overflow:ellipsis;display:block}
@media (max-width:380px){.orgsum .v{font-size:var(--fs-sm)}}
.orgsum .v.weak{color:var(--warn)}
#orgLegs{background:var(--bg-2);border-radius:var(--r-lg);padding:var(--s4);
         margin-bottom:var(--s4)}
#orgLegs .legs{margin-bottom:var(--s3)}

/* ===========================================================
   조직도
   =========================================================== */
.treebox{overflow:auto;background:var(--bg-2);border-radius:var(--r-lg);
         padding:var(--s6) var(--s5);max-height:640px}
.treebox > div{width:max-content;min-width:100%;display:flex;justify-content:center}
.tnode{display:flex;flex-direction:column;align-items:center;position:relative}
/* ── 연결선 ──────────────────────────────────────────────────
 *
 * 부모 밑에서 **수직으로 내려와 → 가로로 뻗어 → 다시 수직으로 내려가** 자식에
 * 닿는 ㄱ자다. 대각선으로 잇지 않는다 — 좌우 하부의 크기가 다르면 선이 길게
 * 기울어 서로 교차하고, 깊어질수록 어느 선이 어디로 가는지 못 읽는다.
 *
 * 세 토막이 이어져야 한 줄로 보인다:
 *   `.tkids::before`  부모 상자 밑 → 가로선   (세로 var(--s5))
 *   `.tkid::after`    형제들을 잇는 가로선     (첫째 가운데 ~ 막내 가운데)
 *   `.tkid::before`   가로선 → 자식 상자 위    (세로 var(--s3))
 *
 * ⚠️ 토막 길이는 `.tkids` 의 `margin-top`·`.tkid` 의 `padding-top` 과 **같은
 *    값이어야 한다.** 하나만 바꾸면 선이 중간에서 끊기거나 상자를 뚫는다.
 * ⚠️ 가로선은 `.tkid` 마다 한 도막씩 그려 이어 붙인다. 형제 사이의 틈
 *    (`gap`)만큼 양옆으로 더 늘려야 도막이 붙는다 — 안 늘리면 자식 수만큼
 *    점선이 된다.
 * ⚠️ 첫째는 제 가운데서 오른쪽만, 막내는 왼쪽만 그린다. 안 그러면 가로선이
 *    맨 바깥 자식 바깥으로 튀어나와 허공에서 끝난다.
 * ⚠️ 외동(`:only-child`)이면 좌우가 모두 50% 라 가로선은 저절로 사라지고
 *    세로 두 토막만 남아 곧은 직선이 된다 — 따로 숨기지 마라.
 */
/*
 * ⚠️ 치수는 **여기 세 줄에서만** 정한다. 여백과 선 길이를 따로 적으면
 *    반드시 한쪽만 고치는 날이 오고, 그날 선은 중간에서 뜨거나 상자를
 *    뚫는다 — 좁은 화면 규칙이 `margin-top` 만 16px 로 줄이고 선은 20px
 *    로 남겨 둬서 실제로 4px 씩 삐져나와 있었다.
 *    좁은 화면에서 좁히고 싶으면 **이 변수만** 덮어써라(아래 media 참고).
 */
/*
 * ⚠️ 형제 사이 틈은 `gap` 이 아니라 **`.tkid` 의 좌우 여백**으로 만든다.
 *    `gap` 으로 두면 가로선 도막이 그 틈을 건너려고 상자 밖으로 삐져나가야
 *    하고, 그러면 넘침 검사에 걸릴뿐더러 배율을 주는 자리에서 어긋난다.
 *    여백으로 두면 도막이 제 상자 안에서 끝나면서도 옆 도막과 딱 맞닿는다.
 */
.tkids{--drop:var(--s5);        /* 부모 상자 밑 ~ 가로선 */
       --rise:var(--s3);        /* 가로선 ~ 자식 상자 위 */
       /* ⚠️ 형제 틈은 **짝수 눈금**으로 둔다. 좌우로 반씩 나눠 여백을 주므로
          눈금의 절반이 다시 눈금 위에 떨어져야 한다 — `--s3`(12px)를 쓰면
          6px 이 되어 이 앱 어디에도 없는 값이 된다. */
       --sib:var(--s4);         /* 형제 사이 틈 */
       display:flex;margin-top:var(--drop);position:relative}
.tkids::before{content:'';position:absolute;top:calc(-1 * var(--drop));left:50%;
               margin-left:-.5px;width:1px;height:var(--drop);background:var(--tree-line)}
.tkid{display:flex;flex-direction:column;align-items:center;position:relative;
      padding-top:var(--rise);
      padding-left:calc(var(--sib) / 2);padding-right:calc(var(--sib) / 2)}
.tkid::before{content:'';position:absolute;top:0;left:50%;margin-left:-.5px;
              width:1px;height:var(--rise);background:var(--tree-line)}
.tkid::after{content:'';position:absolute;top:0;height:1px;background:var(--tree-line);
             left:0;right:0}
.tkid:first-child::after{left:50%}
.tkid:last-child::after{right:50%}
.tbox{background:var(--node);border-radius:var(--r-md);padding:var(--s2) var(--s3);
      min-width:132px;text-align:center;font-size:var(--fs-sm);line-height:var(--lh-snug);
      box-shadow:var(--sh-1)}

.tbox.root{background:var(--brand);color:#fff;box-shadow:none}
.tbox.root .c{color:rgba(255,255,255,.7)}
.tbox.root .lr{color:rgba(255,255,255,.8)}
.tbox.root .lr b{color:#fff}
.tbox.empty{background:none;box-shadow:inset 0 0 0 1px var(--bg-3);color:var(--ink-3);
            min-width:62px;padding:var(--s2);font-size:var(--fs-2xs)}
/* 한 번에 그리는 인원을 넘어 잘린 자리.
   ⚠️ 빈자리와 **눈으로 갈라져야 한다.** 빈자리는 새 회원이 들어갈 수 있는
      자리고, 이쪽은 이미 사람이 있는데 안 그려진 자리다. 같은 회색으로
      그리면 운영자가 찍었다가 SLOT_TAKEN 을 맞는다. */
.tbox.more{background:none;box-shadow:inset 0 0 0 1px var(--brand);color:var(--brand);
           min-width:62px;padding:var(--s2);font-size:var(--fs-2xs);
           font-weight:var(--fw-semi);cursor:pointer}
.tbox.more:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.tbox .n{font-weight:var(--fw-bold);letter-spacing:var(--ls-base)}
/* 조직도 상자 안의 상태 딱지 — 탈퇴·휴면.
   ⚠️ 줄을 새로 만들지 마라. 상자가 한 줄 높아지면 조직이 깊을 때 화면 밖으로
      밀려난다. 이름 줄 끝에 붙인다. */
.tbox .st{font-size:var(--fs-2xs);font-weight:var(--fw-semi);letter-spacing:0;
          border-radius:var(--r-sm);padding:0 var(--s1);vertical-align:middle;
          background:var(--bg-2);color:var(--ink-3)}
.tbox .st.no{background:var(--bad-bg);color:var(--bad)}
/* 인정코드 — 관리자 조직도에서만 뜬다. 회원용은 키 자체가 안 내려온다(036) */
.tbox .st.rec{background:var(--warn-bg);color:var(--warn)}
.tbox.root .st.rec{background:rgba(255,255,255,.22);color:#fff}

/* ── 등급 색 (045) ─────────────────────────────────────────
   어떤 다리에 큰 패키지가 붙었는지 **글자를 읽기 전에** 보이게 한다.

   색은 고른 게 아니라 남은 색을 전부 조합해 색약 시뮬레이션으로 걸러
   남은 것이다. 앰버 계열은 루트 상자·인정 뱃지가 이미 쓰고, 빨강은
   탈퇴·위험이라 쓸 수 없다. 남은 다섯(파랑·청록·자홍·초록·보라)의
   조합 10가지 중 라이트·다크 양쪽을 통과한 건 둘뿐이었다.
   그중 색 간 거리가 가장 넓은 쪽(적·녹색맹 ΔE 13, 정상 시야 27.5).

   ⚠️ 색을 **혼자 두지 마라.** 등급 이름이 상자에 그대로 적혀 있어야 한다 —
      라이트에서 자홍(#e87ba4)은 면 대비 2.49:1 로 3:1 을 못 넘는다.
      그 글자가 유일한 받침이다.
   ⚠️ 보라를 도로 넣지 마라. 다크에서 파랑과 적색맹 기준 ΔE 1.9 —
      사실상 같은 색이다.
   ⚠️ 바탕을 진하게 칠하지 마라. 상자 안에 아이디·실적 숫자가 들어 있다.
      신호는 **왼쪽 띠**가 지고, 바탕은 거들기만 한다.
   ⚠️ 여기 한 곳에서만 정한다. 마이오피스와 어드민이 같은 `renderTree` 를
      쓰므로, 화면에서 또 칠하면 같은 회원이 두 색으로 보인다. */
:root{
  --gc-seller:#2a78d6;      --gc-seller-bg:#eaf2fd;
  --gc-agency:#008300;      --gc-agency-bg:#e6f4e8;
  --gc-distributor:#e87ba4; --gc-distributor-bg:#fdeef3;
}
:root[data-theme="dark"],:root[data-theme="system"]{
  --gc-seller:#3987e5;      --gc-seller-bg:#151d2b;
  --gc-agency:#008300;      --gc-agency-bg:#121d15;
  --gc-distributor:#d55181; --gc-distributor-bg:#1f1620;
}
@media (prefers-color-scheme:light){
  :root[data-theme="system"]{
    --gc-seller:#2a78d6;      --gc-seller-bg:#eaf2fd;
    --gc-agency:#008300;      --gc-agency-bg:#e6f4e8;
    --gc-distributor:#e87ba4; --gc-distributor-bg:#fdeef3;
  }
}
.tbox.g-SELLER      {--gc:var(--gc-seller);      --gc-bg:var(--gc-seller-bg)}
.tbox.g-AGENCY      {--gc:var(--gc-agency);      --gc-bg:var(--gc-agency-bg)}
.tbox.g-DISTRIBUTOR {--gc:var(--gc-distributor); --gc-bg:var(--gc-distributor-bg)}
/*
 * ⚠️ 루트는 `:not(.root)` 로 **아예 빼 둔다.** 이기려 들지 마라 —
 *    루트의 금색 면은 그라데이션(`--fill`)이라, 더 센 선택자로 덮으면
 *    단색이 얹혀 그라데이션이 죽는다. 실제로 마이오피스에서 본인이
 *    총판점이면 루트가 갈색 단색으로 보였다. 루트는 한 곳에서만 칠한다.
 */
.tbox:not(.root).g-SELLER,
.tbox:not(.root).g-AGENCY,
.tbox:not(.root).g-DISTRIBUTOR{
  background:var(--gc-bg);
  border-left:3px solid var(--gc)}
.tbox .c .gr{font-weight:var(--fw-semi);color:inherit}
.tbox:not(.root).g-SELLER .c .gr,
.tbox:not(.root).g-AGENCY .c .gr,
.tbox:not(.root).g-DISTRIBUTOR .c .gr{color:var(--gc)}
/* 탈퇴한 자리 — 남아 있지만 죽은 자리다. 눌러 보기 전에 눈으로 갈라져야 한다 */
.tbox.dead{opacity:.62}
.tbox.dead .n{text-decoration:line-through;text-decoration-thickness:1px}
.tbox .c{font-size:var(--fs-2xs);color:var(--ink-3)}
.tbox .lr{font-size:var(--fs-2xs);color:var(--ink-2);margin-top:var(--s1);display:flex;
          gap:var(--s2);justify-content:center;font-variant-numeric:tabular-nums}
.tbox .lr b{font-weight:var(--fw-bold);color:var(--brand)}
/* 가입일 — 계보도 상자 맨 아래 한 줄(45단계). 숫자만이라 작게, 흐리게 */
.tbox .jd{font-size:var(--fs-2xs);color:var(--ink-3);margin-top:var(--s1);font-variant-numeric:tabular-nums;letter-spacing:.01em}
.tbox.root .jd{color:var(--on-accent-3)}
/* 내 현황 — 누적 실적·소실적 누적 (A·B 균형 카드 아래) */
.lifeline{margin-top:var(--s4);padding-top:var(--s3);border-top:1px dashed var(--line);
  display:flex;flex-direction:column;gap:var(--s2);font-size:var(--fs-xs);font-variant-numeric:tabular-nums}
.lifeline .row2{display:flex;justify-content:space-between;gap:var(--s3);align-items:baseline;min-width:0}
.lifeline .k{color:var(--ink-3)}
.lifeline .v{color:var(--ink-2);text-align:right}
.lifeline .v b{color:var(--ink);font-weight:var(--fw-bold)}
.lifeline .mut{color:var(--ink-3)}
.lifeline .track{margin-top:var(--s1);height:var(--s2);background:var(--bg-3);border-radius:var(--r-full);overflow:hidden}
.lifeline .track i{display:block;height:100%;background:var(--brand);border-radius:var(--r-full);transition:width var(--t-slow) var(--e-out)}
.legtag{position:absolute;top:calc(-1 * var(--s2));left:50%;transform:translateX(-50%);
        font-size:var(--fs-2xs);font-weight:var(--fw-bold);padding:0 var(--s1);
        border-radius:var(--r-full);background:var(--bg-3);color:var(--ink-3)}

/* 후원인 찾기 칸.
   ⚠️ `size` 만 믿지 마라 — 360px 화면에서 칸 하나가 줄을 밀어내 화면이
      통째로 가로로 넘쳤다(간격 검사가 잡았다). 줄어들 수 있게 열어 둔다. */
.slotbar{gap:var(--s2)}
.slotbar > label{flex:1 1 150px;min-width:0}
.slotbar input{width:100%;min-width:0}

.slots{display:flex;flex-wrap:wrap;gap:var(--s1);max-height:270px;overflow-y:auto}
.slot{font-size:var(--fs-xs);font-weight:var(--fw-medium);background:var(--bg);
      color:var(--ink-2);border:0;border-radius:var(--r-full);padding:var(--s1) var(--s3);
      cursor:pointer;font-family:var(--font);box-shadow:inset 0 0 0 1px var(--bg-3)}
.slot:hover{color:var(--brand);box-shadow:inset 0 0 0 1px var(--brand)}
.slot.on{background:var(--brand);color:#fff;box-shadow:none}
/* 못 고르는 자리. **감추지 말고 이유와 함께 보여 준다** — 없어 보이면
   운영자는 "저 사람이 안 나온다" 로 읽고, 그건 고장으로 읽힌다. */
.slot.off{opacity:.5;cursor:not-allowed}
.slot.off:hover{color:var(--ink-3);box-shadow:inset 0 0 0 1px var(--bg-3)}
/* 자리 한 칸이 두 줄(이름 / 이유)이 되는 자리 — 자리 검색 결과 */
.slot > span{display:block;font-size:var(--fs-2xs);opacity:.7;font-weight:var(--fw-medium)}

/* ===========================================================
   표 — 가로로 넘칠 때 잘렸다는 걸 보이게 한다
   =========================================================== */
.tw{position:relative}
/* 오른쪽 끝을 흐리게 해서 더 있다는 걸 알린다 */
.tw.over::after{content:'';position:absolute;top:0;bottom:0;right:0;width:var(--s10);
                pointer-events:none;border-radius:0 var(--r-lg) var(--r-lg) 0;
                background:linear-gradient(90deg,transparent,var(--bg-2) 72%);
                box-shadow:inset -1px 0 0 var(--bg-3)}
td .sub{display:block;font-size:var(--fs-2xs);color:var(--ink-3);
        font-weight:var(--fw-medium);margin-top:1px}
/*
 * 사람이 적은 글(메모·사유)은 **줄을 바꾼다.**
 *
 * 칸이 `nowrap` 인데 그 안에 한 줄짜리 메모가 들어가면 그 한 줄이 열 폭을
 * 정해 버린다 — 출금 목록에서 반려 사유 한 건이 `검토자` 열을 400px 로
 * 벌려 놓았고, 같은 열의 다른 줄은 `admin1` 넉 자뿐이라 그 사이가 통째로
 * 빈 칸으로 보였다. 폭을 글자 수로 묶고 넘치면 접는다.
 * ⚠️ px 로 묶지 마라 — 글씨 크기가 바뀌면 같이 움직여야 한다.
 */
td .sub.memo{white-space:normal;min-width:18ch;max-width:24ch}

/*
 * 일괄 처리 단추는 **표 머리글 안**, 전체선택 네모 바로 왼쪽에 산다.
 *
 * 목록 위에 따로 줄을 두고 고를 때만 띄웠더니, 단추가 생겼다 사라지면서
 * 표가 아래로 밀렸다. 자리가 고정이면 운영자는 그 자리를 외운다.
 * ⚠️ 고른 게 없어도 **그대로 둔다.** 눌렀을 때 "고른 건이 없습니다" 라고
 *    말해 주는 편이, 단추가 사라져서 어디 갔나 찾는 것보다 낫다.
 */
.bulkhead{display:flex;align-items:center;justify-content:flex-end;
          flex-wrap:wrap;gap:var(--s2)}
.bulkhead .n{font-size:var(--fs-xs);color:var(--ink-2);font-weight:var(--fw-medium)}
/* 고르는 칸은 넓힐 이유가 없다 — 남는 폭은 `.fill` 을 단 칸이 먹는다 */
td.pick,th.pick{width:1%;white-space:nowrap;text-align:center}
td.fill,th.fill{width:100%}
td.nw,th.nw{white-space:nowrap}

/* 목록 위 도구줄 — 검색 + 건수 */
.toolbar{display:flex;gap:var(--s2);align-items:center;margin-bottom:var(--s3);flex-wrap:wrap}
.toolbar input[type=search]{width:auto;flex:1;min-width:160px;max-width:280px;margin:0;
                            padding:var(--s2) var(--s3);font-size:var(--fs-md)}
.toolbar .count{font-size:var(--fs-xs);color:var(--ink-3);margin-left:auto;
                font-variant-numeric:tabular-nums}
.more{display:block;width:100%;margin:var(--s2) 0 var(--s3)}

/* ── 목록 도구줄 — 검색 · 상태 · 기간 · 쪽당 개수 · 내려받기 ──────────
   한 줄에 다 들어가지 않으면 접힌다. 좁은 화면에서 옆으로 스크롤되게
   두지 마라 — 검색 단추가 화면 밖으로 나간다. */
.listbar{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap;
         margin-bottom:var(--s3)}
.listbar input[type=search]{width:auto;flex:1 1 180px;min-width:0;max-width:280px;
         margin:0;padding:var(--s2) var(--s3);font-size:var(--fs-md)}
.listbar select{width:auto;margin:0;padding:var(--s2) var(--s3);font-size:var(--fs-sm)}
.listbar input[type=date]{width:auto;margin:0;padding:var(--s2) var(--s3);
         font-size:var(--fs-sm);min-width:0}
.listbar .dates{display:flex;gap:var(--s1);align-items:center;min-width:0}
.listbar .dates .tilde{color:var(--ink-3);font-size:var(--fs-sm)}
/* 내려받기는 늘 오른쪽 끝 — 눈이 찾는 자리를 고정한다 */
.listbar [data-export]{margin-left:auto}

/* 쪽 이동 줄 */
.pager{display:flex;gap:var(--s3);align-items:center;flex-wrap:wrap;
       margin:var(--s3) 0}
.pager:empty{display:none}
.pager .count{font-size:var(--fs-xs);color:var(--ink-3);
              font-variant-numeric:tabular-nums}
.pager .pg{display:flex;gap:var(--s1);align-items:center;margin-left:auto}
.pager .pg b{font-size:var(--fs-xs);color:var(--ink-2);padding:0 var(--s2);
             font-variant-numeric:tabular-nums}
.pager .pg .btn{min-width:var(--s6)}

/* 목록 합계 — 서버가 센 값이다 */
.sums{display:flex;gap:var(--s4);flex-wrap:wrap;margin-bottom:var(--s3)}
.sums .one{display:flex;gap:var(--s2);align-items:baseline;background:var(--bg-2);
           border-radius:var(--r-sm);padding:var(--s2) var(--s3)}
.sums .k{font-size:var(--fs-xs);color:var(--ink-3)}
.sums b{font-size:var(--fs-md);letter-spacing:var(--ls-num);
        font-variant-numeric:tabular-nums}

/* ── 찾아서 고르는 칸 (회원 고르기) ──────────────────────────────
   ⚠️ 목록을 `position:absolute` 로 띄운다. 흐름에 두면 열릴 때마다
      아래 내용이 밀려 내려가 누르려던 자리가 달아난다. */
/* ⚠️ flex 자식은 min-content 폭 아래로 줄지 않는다. `input` 은 기본 `size`
      때문에 min-content 가 20글자쯤이라, min-width:0 을 빠뜨리면 360px 에서
      화면 전체가 옆으로 스크롤된다 (CLAUDE.md). */
.picker{position:relative;display:block;min-width:0;flex:1 1 160px}
/* ⚠️ 라벨 안의 span 은 위에서 `flex:none` 으로 굳혀 두었다(글자가 세로로
   접히지 말라고). 찾아 고르는 칸은 그 예외다 — 안 풀면 입력칸 넓이 그대로
   버텨서 카드를 뚫는다. */
.row label > span.picker{flex:1 1 160px;white-space:normal;min-width:0}
/* ⚠️ 좁은 화면 규칙(`.card .row.wrap input{width:auto}`)이 더 구체적이라
   그냥 두면 입력칸이 제 글자수(size)만큼 벌어져 카드를 뚫는다. 여기서
   이겨야 한다 — 선택자를 짧게 줄이지 마라. */
.picker > input,.card .row.wrap .picker > input{margin:0;width:100%;min-width:0}
.pickmenu{position:absolute;z-index:40;left:0;right:0;top:calc(100% + var(--s1));
          max-height:260px;overflow:auto;background:var(--surface);
          border:1px solid var(--hair);border-radius:var(--r-md);
          box-shadow:var(--glow);padding:var(--s1)}
.pickmenu.hide{display:none}
.pickmenu button{display:flex;width:100%;gap:var(--s2);align-items:baseline;
                 justify-content:space-between;text-align:left;cursor:pointer;
                 background:none;border:0;border-radius:var(--r-sm);
                 padding:var(--s2) var(--s3);font-family:var(--font);
                 font-size:var(--fs-sm);color:var(--ink)}
.pickmenu button:hover,.pickmenu button.on{background:var(--bg-2)}
.pickmenu button code{font-size:var(--fs-xs);color:var(--ink-3);
                      background:none;padding:0}
.pickmenu .none{padding:var(--s3);font-size:var(--fs-sm);color:var(--ink-3)}

/*
 * 위로 뒤집힌 목록 — `placeMenu()`(lib.js)가 자리를 재서 붙여 준다.
 *
 * ⚠️ 세 종류 메뉴가 모양이 달라도 뒤집는 규칙은 하나다. 한 군데서만
 *    처리하면 나머지 둘은 계속 화면 밖으로 나간다 — 실제로 회원 홈의
 *    센터 고르는 칸이 하단 탭바에 깔려 있었다.
 * ⚠️ `bottom` 으로 뒤집고 `top` 은 반드시 `auto` 로 되돌린다. CSS 가
 *    위에서 `top:calc(100% + …)` 을 이미 걸어 뒀으므로, 안 풀면 위아래가
 *    동시에 걸려 목록이 늘어난다.
 */
.selmenu.up,.pickmenu.up,.datemenu.up{
  top:auto;bottom:calc(100% + var(--s1))}

/* ── 직접 그린 고르는 칸 (`mountSelect`) ──────────────────────
   왜 `<select>` 를 안 쓰나: 펼친 목록은 브라우저가 그린다. 우리 글꼴도 색도
   어둠모드도 안 먹고, 안드로이드·iOS·데스크톱이 각각 다르게 생겼다.
   ⚠️ `.selmenu` 는 절대 위치다. `overflow:hidden` 인 조상 밑에 두면 잘린다. */
.selbox{position:relative;display:block;min-width:0}
.row label > span.selbox{flex:1 1 180px;white-space:normal;min-width:0}

.selbtn{display:flex;width:100%;align-items:center;gap:var(--s2);
  justify-content:space-between;cursor:pointer;text-align:left;
  margin:0;padding:var(--s3) var(--s4);min-height:44px;
  border-radius:10px;border:1px solid var(--hair);background:var(--surface-2);
  font-family:var(--font);font-size:var(--fs-md);color:var(--ink);
  transition:border-color var(--t-base) var(--e-out),box-shadow var(--t-base) var(--e-out)}
.selbtn:focus-visible{outline:2px solid var(--brand);outline-offset:0}
.selbox.off .selbtn{cursor:default;background:var(--bg-2)}
/* ⚠️ 잠근 칸을 회색으로 죽이지 마라 — "고장났다" 로 읽힌다. 글자는 또렷하게
      두고 자물쇠로 일부러 잠갔다는 것을 말한다. */
.sellab{flex:1 1 auto;min-width:0;overflow-wrap:anywhere}
.sellab.ph{color:var(--ink-3)}
.selcaret{flex:none;width:18px;height:18px;fill:none;stroke:currentColor;
  stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;opacity:.55;
  transition:transform var(--t-fast) var(--e-out)}
.selbtn[aria-expanded="true"] .selcaret{transform:rotate(180deg)}
.selbox.off .selcaret{display:none}

.selmenu{position:absolute;z-index:40;left:0;right:0;top:calc(100% + var(--s1));
  max-height:280px;overflow:auto;background:var(--surface);
  border:1px solid var(--hair);border-radius:var(--r-md);
  box-shadow:var(--glow);padding:var(--s1)}
.selmenu.hide{display:none}
.selmenu button{display:flex;width:100%;gap:var(--s2);align-items:center;
  justify-content:space-between;text-align:left;cursor:pointer;
  background:none;border:0;border-radius:var(--r-sm);
  padding:var(--s2) var(--s3);min-height:40px;
  font-family:var(--font);font-size:var(--fs-sm);color:var(--ink)}
.selmenu button:hover,.selmenu button.on{background:var(--bg-2)}
.selmenu button.sel{font-weight:var(--fw-semi)}
.selmenu button[disabled]{opacity:.45;cursor:default}
.selmenu button code{flex:none;font-size:var(--fs-xs);color:var(--ink-3);
  background:none;padding:0}

/* 로그인 카드 안에서는 카드의 입력칸과 똑같이 보여야 한다.
   ⚠️ 카드는 제 배경(--ground)과 글자색(--card-ink)을 따로 쓴다. 공용 모양
      그대로 두면 이 칸만 회색으로 떠서 폼 한가운데가 튄다. */
.login .ctl .selbox{display:block}
.login .ctl .selbtn{background:var(--ground);border-color:var(--hair);
  color:var(--card-ink);padding:var(--s3) var(--s4);min-height:46px}
.login .ctl .selbtn:focus-visible{outline:none;border-color:var(--accent-2);
  box-shadow:0 0 0 3px rgba(232,163,61,.18)}
.login .ctl .sellab.ph{color:var(--card-ink-3)}
.login .ctl .selmenu{background:var(--ground);border-color:var(--hair)}
.login .ctl .selmenu button{color:var(--card-ink)}
.login .ctl .selmenu button:hover,.login .ctl .selmenu button.on{background:var(--surface-2)}

/* 바꿔 끼운 원래 칸(`<select>` · `<input type=date>`) — 값의 주인이라
   지우지 않고 감춘다.
   ⚠️ 선택자를 `select.selnative` 로 좁히지 마라. 날짜칸은 `input` 이라
      안 걸리고, 그 칸만 브라우저 기본 달력이 그대로 보인다 (여기서 겪었다).
   ⚠️ `opacity:0` 으로 두지 마라. 눌러서 브라우저 기본 목록·달력이 열린다. */
.selnative{display:none !important}

/* ── 날짜 고르기 (`enhanceDate`) ────────────────────────────── */
.datebox{position:relative;display:inline-block;min-width:0}
.datebtn{min-width:150px}
.datebtn .selcaret{stroke-width:1.6;opacity:.6}
.datemenu{position:absolute;z-index:40;left:0;top:calc(100% + var(--s1));
  width:min(300px,86vw);background:var(--surface);
  border:1px solid var(--hair);border-radius:var(--r-md);
  box-shadow:var(--glow);padding:var(--s3)}
.datemenu.hide{display:none}
/* ⚠️ 오른쪽 끝에 있는 칸은 달력이 화면 밖으로 나간다 — 그 칸만 오른쪽에 건다 */
.row > label:last-of-type .datemenu,.listbar > label:last-of-type .datemenu{left:auto;right:0}

.dhd{display:flex;align-items:center;justify-content:space-between;
  margin-bottom:var(--s2);font-size:var(--fs-sm)}
.dnav{background:none;border:0;cursor:pointer;color:var(--ink-2);
  font-size:var(--fs-lg);line-height:1;padding:var(--s1) var(--s3);
  border-radius:var(--r-sm);min-width:32px;min-height:32px}
.dnav:hover{background:var(--bg-2);color:var(--ink)}

.dwk,.dgrid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}
.dwk span{text-align:center;font-size:var(--fs-xs);color:var(--ink-3);padding:var(--s1) 0}
.dgrid button{background:none;border:0;cursor:pointer;color:var(--ink);
  font-family:var(--font);font-size:var(--fs-sm);
  aspect-ratio:1;min-height:34px;border-radius:var(--r-sm)}
.dgrid button:hover{background:var(--bg-2)}
.dgrid button.today{box-shadow:inset 0 0 0 1px var(--hair)}
.dgrid button.on{background:var(--brand);color:#fff;font-weight:var(--fw-semi)}
.dfoot{display:flex;gap:var(--s2);justify-content:space-between;margin-top:var(--s3)}

/* ── 국가 뱃지 ──────────────────────────────────────────────
   조직도 상자와 내정보에 같이 쓴다. 국기는 이모지라 글꼴을 타지 않는다. */
.flag{display:inline-flex;align-items:center;gap:var(--s1);
  font-size:var(--fs-xs);line-height:1;white-space:nowrap}
.flag .em{font-size:1.15em;line-height:1}
.flag.pill{padding:2px var(--s2);border-radius:999px;
  background:var(--bg-2);color:var(--ink-2)}
/* 조직도 상자 안에서는 이름 줄 옆에 붙는다 — 줄을 새로 만들지 않는다 */
.tbox .flag{margin-left:var(--s1);vertical-align:middle}

/* ── 확인·알림·입력 대화상자 (`ask` / `tell` / `askText`) ──────
   브라우저 기본 창을 쓰지 않는 이유는 lib.js 의 `openDialog` 머리말에 있다. */
.dlgback{position:fixed;inset:0;z-index:200;display:flex;
  align-items:center;justify-content:center;padding:var(--s5);
  background:rgba(8,11,17,.55);opacity:0;
  transition:opacity var(--t-base) var(--e-out)}
.dlgback.in{opacity:1}
@supports (backdrop-filter: blur(2px)) { .dlgback{backdrop-filter:blur(2px)} }

.dlg{width:min(420px,100%);max-height:calc(100dvh - var(--s10));overflow:auto;
  background:var(--surface);border:1px solid var(--hair);
  border-radius:var(--r-lg);box-shadow:var(--glow);
  padding:var(--s6);transform:translateY(8px) scale(.98);
  transition:transform var(--t-base) var(--e-out)}
.dlgback.in .dlg{transform:none}
.dlg h2{margin:0 0 var(--s3);font-size:var(--fs-lg);line-height:var(--lh-snug)}
.dlgbody{margin:0 0 var(--s5);color:var(--ink-2);font-size:var(--fs-sm);
  line-height:var(--lh-base);max-width:60ch}
.dlgbody b{color:var(--ink);font-weight:var(--fw-semi)}

.dlgin{display:block;margin:0 0 var(--s5)}
.dlgin > span{display:block;margin-bottom:var(--s2);
  font-size:var(--fs-xs);color:var(--ink-2)}
.dlgin > span:empty{display:none}
.dlgin input{width:100%;margin:0}

/* ⚠️ 확인을 오른쪽에 둔다. 왼쪽에 두면 취소하려다 확인을 누른다. */
.dlgrow{display:flex;gap:var(--s2);justify-content:flex-end;flex-wrap:wrap}
.dlgrow .btn{min-height:44px}

@media (prefers-reduced-motion: reduce){
  .dlgback,.dlgback .dlg{transition:none}
}

/* 되돌릴 수 없는 작업 앞에 세우는 경고 */
.warnbox{display:block;background:var(--warn-bg);border-radius:var(--r-sm);
         padding:var(--s3) var(--s4);margin-bottom:var(--s3);line-height:var(--lh-snug);
         font-size:var(--fs-sm);color:var(--ink-2);max-width:70ch;
         box-shadow:inset 3px 0 0 var(--warn)}
.warnbox b{color:var(--warn);font-weight:var(--fw-bold)}
/* 막지는 않는 안내 — "곧 필요합니다" 정도. 경고와 같은 자리를 쓰되 덜 세게. */
.warnbox.soft{background:var(--bg-2);box-shadow:inset 3px 0 0 var(--ink-3)}
.warnbox.soft b{color:var(--ink-2)}
/* 경고 상자 안의 항목 목록 — 탈퇴 점검처럼 "무엇을 정리해야 하는가" 를 나열할 때 */
.mclist{margin:var(--s2) 0 0;padding-left:var(--s4);list-style:disc}
.mclist li{margin-top:var(--s1)}

/* 메일 미리보기 — sandbox iframe 이라 안쪽 스타일은 이 파일과 무관하다 */
.mailframe{width:100%;height:420px;border:1px solid var(--line);
           border-radius:var(--r-md);background:#fff;display:block}
.mailtext{white-space:pre-wrap;font-family:var(--mono);font-size:var(--fs-xs);
          color:var(--ink-2);background:var(--bg-2);padding:var(--s3);
          border-radius:var(--r-sm);margin:var(--s2) 0 0;overflow-x:auto}

/* ===========================================================
   환경설정 팝오버 — 테마 · 언어
   =========================================================== */
.prefsbtn{background:none;border:0;padding:var(--s2);margin:0;cursor:pointer;
          color:var(--on-dark-2);display:grid;place-items:center;border-radius:var(--r-sm);
          flex:none}
.prefsbtn:hover{color:var(--on-dark);background:rgba(255,255,255,.06)}
.prefsbtn svg{width:19px;height:19px;stroke:currentColor;fill:none;
              stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.prefsbtn.on{color:var(--brand)}

/* 알림 종 */
.bellbtn{position:relative;background:none;border:0;padding:var(--s2);margin:0;cursor:pointer;
         color:var(--on-dark-2);display:grid;place-items:center;border-radius:var(--r-sm);flex:none}
.bellbtn:hover{color:var(--on-dark);background:rgba(255,255,255,.06)}
.bellbtn svg{width:19px;height:19px;stroke:currentColor;fill:none;
             stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.bellbtn .dot{position:absolute;top:4px;right:4px;width:8px;height:8px;border-radius:var(--r-full);
              background:var(--bad);box-shadow:0 0 0 2px var(--dark)}
.bellbtn.on{color:var(--brand)}

.prefs{position:fixed;z-index:80;width:264px;max-width:calc(100vw - var(--s8));
       background:var(--bg);color:var(--ink);border-radius:var(--r-lg);
       box-shadow:0 10px 40px rgba(20,24,31,.22),0 0 0 1px var(--line);
       padding:var(--s4)}
.prefs[hidden]{display:none}
.prefs .grp{margin-bottom:var(--s4)}
.prefs .grp:last-child{margin-bottom:0}
.prefs .lb{font-size:var(--fs-xs);color:var(--ink-3);margin-bottom:var(--s2);
           font-weight:var(--fw-medium)}
.prefs .seg{width:100%}
.prefs .seg button{flex:1;justify-content:center;white-space:nowrap;padding-inline:var(--s2)}
.prefsveil{position:fixed;inset:0;z-index:70;background:transparent}
/* 로그인 화면에서는 박스 우상단에 얹는다 */
.login .box{position:relative}
.prefsbtn.onlogin{position:absolute;top:var(--s3);right:var(--s3);color:var(--ink-3)}
.prefsbtn.onlogin:hover{color:var(--ink);background:var(--bg-2)}
.prefsveil[hidden]{display:none}

/* 좁은 화면 전용 햄버거 — 넓은 화면에서는 사이드바가 늘 보이므로 숨긴다 */
.menubtn{display:none;place-items:center;flex:none;background:none;border:0;cursor:pointer;
         padding:var(--s2);margin:0;border-radius:var(--r-sm);color:var(--ink-3)}
.menubtn:hover{color:var(--ink);background:var(--bg-2)}
.menubtn svg{width:20px;height:20px;stroke:currentColor;fill:none;stroke-width:1.9;
             stroke-linecap:round}

/* ===========================================================
   모바일 (≤820px)
   =========================================================== */
.tabbar{display:none}

@media (max-width:820px){
  .shell{flex-direction:column}

  /* 상단 헤더는 밝게 — 한국 금융앱은 상단을 어둡게 덮지 않는다 */
  .side{width:100%;flex-direction:row;align-items:center;justify-content:space-between;
        gap:var(--s2);padding:var(--s2) var(--s4) calc(var(--s2) + env(safe-area-inset-top,0px));
        position:sticky;top:0;z-index:40;
        background:var(--bg);color:var(--ink);box-shadow:0 1px 0 var(--line)}
  .side nav,.sidefoot{display:none}

  /* 어드민은 탭이 8개라 하단바를 못 쓴다 — 햄버거로 여는 서랍 */
  .shell.drawer .side{flex-wrap:wrap}
  .shell.drawer .side nav{display:flex;order:3;width:100%;flex-direction:row;
                          flex-wrap:wrap;gap:var(--s1);padding:var(--s3) 0 0}
  .shell.drawer .side nav button{flex:1 1 44%;text-align:center;
                                 background:var(--bg-2);color:var(--ink-2)}
  .shell.drawer .side nav button.on{background:var(--brand);color:#fff}
  .shell.drawer .sidefoot{display:block;order:4;width:100%;color:var(--ink-3);
                          padding:var(--s3) 0 0;font-size:var(--fs-2xs)}
  .menubtn{display:grid}

  /* ── 모바일 상단 — 심볼만 ─────────────────────────────────
     ⚠️ 글자 로고(`마이오피스`)를 지운다. 아래 탭바가 이미 "지금 어디" 를
        말해 주는데 위에서 또 이름을 얹으면, 좁은 폭에서 이름·코드·알림·
        로그아웃이 서로 밀려 줄이 흔들린다. 심볼 하나면 충분하다. */
  .brand{padding:0;gap:var(--s2);flex:none}
  .brand em{display:none}
  .brand > div{display:none}
  .brand .dot{width:30px;height:30px;border-radius:var(--r-md);font-size:var(--fs-md)}
  /* 어드민은 하단바가 없어서 상단 이름이 유일한 좌표다 — 거기만 남긴다 */
  .shell.drawer .brand > div{display:block}
  .shell.drawer .brand strong{color:var(--ink);font-size:var(--fs-base)}
  /* flex 자식은 min-content 아래로 줄지 않는다. min-width:0 이 없으면
     좁은 화면에서 헤더가 넘쳐 페이지 전체가 옆으로 스크롤된다. */
  .top{padding:0;min-width:0;flex:1;gap:var(--s2)}
  .who{text-align:right;color:var(--ink-3);flex:1;min-width:0}
  .who b{color:var(--ink);font-size:var(--fs-sm)}
  .logout{border-color:var(--bg-3);color:var(--ink-3)}
  .logout:hover{color:var(--ink);border-color:var(--ink-3)}
  .prefsbtn,.bellbtn{color:var(--ink-3)}
  .prefsbtn:hover,.bellbtn:hover{color:var(--ink);background:var(--bg-2)}
  .bellbtn .dot{box-shadow:0 0 0 2px var(--bg)}
  .prefs{left:var(--s4);right:var(--s4);width:auto;max-width:none}

  main{padding:var(--s6) var(--s4) calc(var(--tabbar-h) + var(--s6) + var(--support-h) + var(--s3) + env(safe-area-inset-bottom,0px))}

  /* 예산 바 — 좁으면 라벨이 겹친다. 막대만 남기고 설명은 아래 범례로 */
  .bar{font-size:0;height:var(--s6)}
  .bar > div{color:transparent !important;padding:0}
  .barlegend{display:flex}
  .barkey{flex-direction:column;align-items:flex-start;gap:var(--s1)}

  /* 폼 한 줄에 여러 컨트롤 — 좁으면 입력은 한 줄 전체, 버튼끼리는 나눠 쓴다 */
  .card .row.wrap > label{width:100%}
  .card .row.wrap > .btn{flex:1 1 40%}
  .card .row.wrap input,.card .row.wrap select{flex:1;width:auto}

  /* ⚠️ 높이를 풀어 두지 마라(`max-height:none`). 트리가 길어지면 페이지가
     통째로 늘어나서, 배율 단추는 저 아래로 내려가 안 보이고 두 손가락
     제스처는 페이지 스크롤과 싸운다. 창 하나로 가둬 두면 둘 다 해결된다. */
  .treebox{padding:var(--s5) var(--s3);max-height:min(62vh,560px)}
  .tbox{min-width:110px;padding:var(--s2);font-size:var(--fs-xs)}
  .tbox.empty,.tbox.more{min-width:54px}
  /* 좁은 화면에서는 조금 좁힌다 — **변수만** 바꾼다. 선 길이·가로선 폭은
     그 변수에서 나오므로 따로 손댈 것이 없다(위 주석 참고). */
  .tkids{--drop:var(--s4);--sib:var(--s2)}

  /* ── 하단 탭바 ──────────────────────
     레퍼런스(Navigation Tabs V4)의 방식: 쉬는 탭은 아이콘만 두고,
     고른 탭만 알약이 가로로 펴지면서 이름이 나온다.
     ⚠️ 다섯 개 이름을 늘 펴 두면 360px 에서 글자가 줄바꿈되거나
        잘린다. 하나만 펴면 그 문제가 사라지고 "지금 여기" 도 더 잘 보인다. */
  .tabbar{
    display:flex;align-items:center;position:fixed;left:0;right:0;bottom:0;z-index:50;
    padding:var(--s2) var(--s3) calc(var(--s2) + env(safe-area-inset-bottom,0px));
    background:var(--bg);box-shadow:var(--sh-2);
  }
  .tabbar button{
    flex:1 1 0;min-width:0;display:flex;align-items:center;justify-content:center;
    background:none;border:0;padding:var(--s3);cursor:pointer;border-radius:var(--r-full);
    font-family:var(--font);font-size:var(--fs-xs);font-weight:var(--fw-semi);
    color:var(--ink-3);letter-spacing:var(--ls-base);white-space:nowrap;
  }
  /* 고른 탭은 이름만큼만 차지한다 — 나머지 공간은 쉬는 탭들이 나눠 갖는다 */
  .tabbar button.on{flex:0 0 auto}
  .tabbar button svg{flex:none;width:22px;height:22px;stroke:currentColor;fill:none;
                     stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
  /* ⚠️ 이름을 `display:none` 으로 감추지 마라. 펴질 때 애니메이션이
     걸리지 않아 탑 하고 나타난다. 0 폭으로 접어 둔다. */
  /* ⚠️ 이름 앞 간격을 margin 으로 주지 마라. 알약 폭은 `scrollWidth` 로 계산하는데
     margin 은 거기에 안 들어가서 간격만큼 좁은 알약이 나온다. padding 은 들어간다. */
  .tabbar button span{
    display:block;overflow:hidden;max-width:0;opacity:0;padding-left:var(--s2);
    transition:max-width var(--t-base) var(--e-out),opacity var(--t-fast) var(--e-out)}
  .tabbar button.on span{max-width:7em;opacity:1;
    transition:max-width var(--t-base) var(--e-out),
               opacity var(--t-base) var(--e-out) 60ms}
  /* ⚠️ position 을 다시 선언하지 마라. 위에서 fixed 로 바닥에 붙여 둔 것을
     relative 로 덮으면 탭바가 문서 흐름으로 돌아가 페이지 맨 아래로 내려간다.
     fixed 도 절대 위치의 기준(containing block)이 되므로 표시자는 그대로 동작한다. */
  /* 활성 탭 뒤에 알약이 미끄러진다. 어디서 어디로 갔는지가 보여야
     잘못 눌렀을 때 되돌아가기 쉽다. */
  /* ⚠️ 폭에 스프링(--e-spring)을 쓰지 마라. 되돌아오는 반동이 이름이 펴지는
     동작과 어긋나, 알약이 글자보다 잠깐 넓어졌다 줄어든다. 이름과 **같은
     곡선·같은 시간**으로 가야 끝까지 붙어 보인다. 이동만 스프링이다. */
  .tabbar .tabind{position:absolute;left:0;top:var(--s2);bottom:calc(var(--s2) + env(safe-area-inset-bottom,0px));
    width:0;z-index:0;background:var(--brand);border-radius:var(--r-full);opacity:0;
    transition:transform var(--t-base) var(--e-spring),width var(--t-base) var(--e-out),
               opacity var(--t-base) var(--e-out)}
  /* 레퍼런스(빨간 영상)의 바닥 글로우 — 고른 탭 아래가 은은하게 탄다.
     ⚠️ `filter:blur()` 로 만들지 마라. 흐림은 별도 레이어로 합성되는데, 알약이
        움직이기 시작하는 프레임에 아직 흐려지지 않은 **네모난 원본**이 그대로
        비친다. box-shadow 는 라운드를 그대로 따라가고 그런 일이 없다. */
  .tabbar .tabind{box-shadow:0 6px 16px -2px rgba(240,185,60,.55)}
  .tabbar button{position:relative;z-index:1;
    transition:color var(--t-base) var(--e-out),flex-grow var(--t-base) var(--e-out)}
  .tabbar button svg{transition:transform var(--t-base) var(--e-spring)}
  .tabbar button.on svg{transform:scale(1.08)}
  .tabbar button:not(.on):active svg{transform:scale(.9)}
  .tabbar button.on{color:var(--on-accent)}
}

@media (prefers-reduced-motion:reduce){
  *{transition:none !important;animation:none !important}
}

/* 체크박스 한 줄 — 네모와 글자를 붙여 둔다 */
label.chk{display:flex;align-items:center;gap:var(--s2);margin:0;
  color:var(--ink);font-size:var(--fs-md);cursor:pointer}
/* ⚠️ 좁은 화면에서 `.card .row.wrap input{flex:1}` 이 체크박스까지 늘려
   네모와 글자가 양끝으로 벌어진다. 체크박스만 빼낸다.
   ⚠️ `accent-color` 로 색만 입히지 마라 — 네모 자체는 여전히 브라우저가
      그린다. 기기마다 모서리도 체크 모양도 다르고 어둠모드에서 튄다.
      `appearance:none` 으로 걷어내고 우리가 그린다. */
label.chk input[type=checkbox],
.card .row.wrap label.chk input[type=checkbox]{
  appearance:none;-webkit-appearance:none;
  flex:none;width:var(--s5);height:var(--s5);margin:0;padding:0;cursor:pointer;
  position:relative;border:1px solid var(--hair);border-radius:5px;
  background:var(--surface-2);
  transition:background var(--t-fast) var(--e-out),border-color var(--t-fast) var(--e-out)}
label.chk input[type=checkbox]:checked{background:var(--brand);border-color:var(--brand)}
/* 체크 표시는 테두리 두 변을 기울여 그린다 — 글꼴에 기대지 않는다 */
label.chk input[type=checkbox]:checked::after{
  content:'';position:absolute;left:34%;top:16%;width:26%;height:52%;
  border:2px solid #fff;border-top:0;border-left:0;transform:rotate(42deg)}
label.chk input[type=checkbox]:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
label.chk input[type=checkbox]:disabled{cursor:not-allowed;opacity:.5}

/* 검색칸 오른쪽의 지우기 `×` 도 브라우저가 그린다 (웹킷).
   ⚠️ 없애고 나면 지울 방법이 필요하다 — 거르기 줄마다 "초기화" 단추가 있다. */
input[type=search]::-webkit-search-cancel-button,
input[type=search]::-webkit-search-decoration{-webkit-appearance:none;appearance:none}

/* 숫자칸의 위아래 화살표도 브라우저가 그린다 — 걷어낸다.
   ⚠️ 키보드 위/아래는 그대로 동작한다. 모양만 없앤 것이다. */
input[type=number]{appearance:textfield;-webkit-appearance:textfield}
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
label.chk:has(input:disabled){color:var(--ink-3);cursor:not-allowed}

/* 권한 표에서 아직 저장하지 않은 칸 — 무엇을 건드렸는지 눈에 남아야 한다 */
td.moved{background:var(--brand-bg)}
td.moved label.chk input[type=checkbox]{border-color:var(--brand)}

/* 임시 비밀번호 — 한 번만 보여 주므로 눈에 잘 띄고 읽기 쉬워야 한다 */
.temppw{font-family:var(--mono);font-size:var(--fs-lg);font-weight:var(--fw-bold);
  letter-spacing:.12em;background:var(--bg);padding:var(--s2) var(--s4);
  border-radius:var(--r-sm);user-select:all}

/* 백업 코드 — 종이에 옮겨 적는 용도라 크고 읽기 쉽게 */
.backupcodes{display:grid;grid-template-columns:repeat(auto-fill,minmax(130px,1fr));
  gap:var(--s2);margin-top:var(--s3)}
.backupcodes code{font-family:var(--mono);font-size:var(--fs-md);font-weight:var(--fw-semi);
  background:var(--bg);padding:var(--s2) var(--s3);border-radius:var(--r-sm);
  text-align:center;letter-spacing:.06em;user-select:all}
.note.warn{color:var(--danger,#c0392b);font-weight:var(--fw-semi)}

/* 편집용 숫자 입력 — 표 칸 안에서 오른쪽 정렬로 */
input.pvin{width:100%;max-width:130px;margin:0;padding:var(--s2);text-align:right;
  font-family:var(--mono);font-size:var(--fs-md);background:var(--field)}

/* ═══════════════════════════════════════════════════════════
   표면 v2 — 떠 있는 판 · 실크 바탕 · 유리

   ⚠️ 여기가 화면의 '얼굴'이다. 위쪽 컴포넌트 규칙은 그대로 두고
      **면(surface)과 색만** 여기서 다시 칠한다. 컴포넌트마다 고치지 마라.

   다크: 브론즈/앰버 실크 위의 유리판
   라이트: 크림 바탕 위에 떠 있는 흰 판
   두 얼굴 다 레퍼런스에 있다 — 영상 8편 중 넷이 라이트다.
   ═══════════════════════════════════════════════════════════ */
:root{
  --accent:#a86a10;          /* 라이트에서 흰 바탕에 읽히는 앰버 */
  --accent-2:#e8a33d;
  --on-accent:#2a1a05;
  /* 금색 면 위의 보조 글자. 투명도를 낮추면 그라데이션 진한 쪽에서 먼저 깨진다 */
  --on-accent-2:rgba(42,26,5,.78); --on-accent-3:rgba(42,26,5,.70);
  --on-accent-bg:rgba(42,26,5,.14);
  --surface:#f4f6f9;
  --surface-2:#eaeef4;
  --hair:rgba(20,24,31,.09);
  --glow:0 1px 2px rgba(20,24,31,.05),0 8px 24px rgba(20,24,31,.07);
  --blur:none;
  --ground:#fff;
  --card-ink:#14181f; --card-ink-2:#5a6472; --card-ink-3:#98a1ae;
  --piece:#fff; --piece-line:rgba(20,24,31,.22); --piece-sh:none;
  --piece-sh2:0 2px 6px rgba(20,24,31,.14);
  --edge-hi:rgba(20,24,31,.15); --edge-lo:rgba(20,24,31,.05); --edge-mid:rgba(20,24,31,.09);
  --shade:rgba(20,24,31,.05);
  --gl-1:rgba(255,255,255,.98); --gl-2:rgba(246,248,251,.92); --gl-3:rgba(232,236,243,.88);
  --sheen:rgba(255,255,255,.9); --card-sh:0 18px 44px rgba(20,24,31,.13);
}
:root[data-theme="dark"],
:root[data-theme="system"]{
  --accent:#e8a33d; --accent-2:#f5c97a; --on-accent:#2a1a05;
  --on-accent-2:rgba(42,26,5,.78); --on-accent-3:rgba(42,26,5,.70);
  --on-accent-bg:rgba(42,26,5,.14);
  --surface:#111419;
  --surface-2:#0c0e12;
  --hair:rgba(255,255,255,.11);
  --glow:0 1px 0 rgba(255,255,255,.05) inset,0 12px 32px rgba(0,0,0,.55);
  --blur:none;
  --ground:#000;
  --card-ink:#e8ecf2; --card-ink-2:#a2acba; --card-ink-3:#6f7987;
  --piece:#262c38; --piece-line:rgba(255,255,255,.34); --piece-sh:none;
  --piece-sh2:0 3px 10px rgba(0,0,0,.75);
  --edge-hi:rgba(255,255,255,.40); --edge-lo:rgba(255,255,255,.06); --edge-mid:rgba(255,255,255,.18);
  --shade:rgba(0,0,0,.28);
  --gl-1:rgba(58,66,80,.98); --gl-2:rgba(32,37,46,.96); --gl-3:rgba(20,24,31,.94);
  --sheen:rgba(255,255,255,.055); --card-sh:0 20px 48px rgba(0,0,0,.8);
}
@media (prefers-color-scheme:light){
  :root[data-theme="system"]{
    --accent:#a86a10; --accent-2:#e8a33d; --on-accent:#2a1a05;
    --on-accent-2:rgba(42,26,5,.78); --on-accent-3:rgba(42,26,5,.70);
    --on-accent-bg:rgba(42,26,5,.14);
    --surface:#f4f6f9; --surface-2:#eaeef4;
    --hair:rgba(20,24,31,.09);
    --glow:0 1px 2px rgba(20,24,31,.05),0 8px 24px rgba(20,24,31,.07);
    --ground:#fff;
    --card-ink:#14181f; --card-ink-2:#5a6472; --card-ink-3:#98a1ae;
    --piece:#fff; --piece-line:rgba(20,24,31,.22); --piece-sh:none;
    --piece-sh2:0 2px 6px rgba(20,24,31,.14);
    --edge-hi:rgba(20,24,31,.15); --edge-lo:rgba(20,24,31,.05); --edge-mid:rgba(20,24,31,.09);
  --shade:rgba(20,24,31,.05);
  --gl-1:rgba(255,255,255,.98); --gl-2:rgba(246,248,251,.92); --gl-3:rgba(232,236,243,.88);
    --sheen:rgba(255,255,255,.9); --card-sh:0 18px 44px rgba(20,24,31,.13);
  --piece:#fff; --piece-line:rgba(20,24,31,.24); --piece-sh:0 2px 8px rgba(20,24,31,.12);
  }
}

/* ── 바탕 ───────────────────────────────────────────────────
   단색이다. 다크는 검정, 라이트는 흰색. 무늬를 깔지 마라 —
   숫자를 읽는 화면이라 바탕이 조용할수록 금액이 또렷하다. */
body{background:var(--ground)}
/* ── 떠 있는 판 ─────────────────────────────────────────────
   카드·리스트·표·통계가 전부 같은 재질이다. 라운드는 --r-lg 하나로 통일. */
.card,.list,.prog,.trio,.stats,.tblwrap,.seg,.empty,.warnbox{
  background:var(--surface);
  border:1px solid var(--hair);
  border-radius:var(--r-lg);
  box-shadow:var(--glow);
  backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
}
.stat{background:transparent;box-shadow:0 0 0 1px var(--hair)}
.trio > *{background:transparent}
.li,.list > *{background:transparent}
.seg{padding:var(--s1)}
.seg button.on,.seg button[aria-selected="true"]{background:var(--surface-2)}

/* 표는 판 안에 들어간다 */
.tblwrap{overflow-x:auto}
table{min-width:420px}
thead th{background:transparent;border-bottom:1px solid var(--hair)}
tbody tr{border-bottom:1px solid var(--hair)}
tbody tr:last-child{border-bottom:0}
tbody tr:hover{background:var(--surface-2)}

/* ⚠️ 유리 위에서 숫자가 흐려지면 안 된다. 금액·PV 는 대비를 되돌려 놓는다 —
   이게 다크·유리로 갈 때 제일 먼저 망가지는 부분이다. */
.n,.big,.v,td.n,th.n,.stat .v,.amount .big{color:var(--ink);font-weight:var(--fw-bold)}
.amount .big{text-shadow:0 1px 0 rgba(0,0,0,.18)}
:root:not([data-theme="dark"]) .amount .big{text-shadow:none}

/* ── 사이드 (PC) — 유리 기둥 ─────────────────────────────── */
.side{background:var(--surface);border-right:1px solid var(--hair);
      backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);color:var(--ink-2)}
.side nav button{color:var(--ink-2)}
.side nav button:hover{color:var(--ink);background:var(--surface-2)}
.side nav button.on{color:var(--on-accent)}
/* 하단 탭바와 같은 앰버 — 밝은 쪽을 위로 두어야 먹색 글씨가 읽힌다 */
.side nav .navind{background:linear-gradient(180deg,var(--accent-2),var(--accent))}
.brand strong{color:var(--ink)}
.brand .dot{background:var(--accent);color:var(--on-accent)}
.sidefoot{color:var(--ink-3);border-top-color:var(--hair)}
/* ⚠️ `.who b{color:#fff}` 는 사이드가 어두웠을 때 규칙이다. 유리 기둥으로
   바뀐 지금은 흰 글씨가 흰 바탕에 얹혀 이름이 사라진다. 되돌려 놓는다. */
.side .who{color:var(--ink-3)}
.side .who b{color:var(--ink)}
.side .logout{border-color:var(--hair);color:var(--ink-3)}
.side .logout:hover{color:var(--ink);border-color:var(--ink-3);background:var(--surface-2)}
.side .bellbtn,.side .prefsbtn,.side .menubtn{color:var(--ink-3)}
.side .bellbtn:hover,.side .prefsbtn:hover,.side .menubtn:hover{
  color:var(--ink);background:var(--surface-2)}
.side .bellbtn .dot{box-shadow:0 0 0 2px var(--surface)}

/* ── 액센트를 앰버로 ───────────────────────────────────────
   영상들의 노란 CTA. 흰 글씨를 얹으면 읽히지 않으므로 먹색을 얹는다. */
.btn.primary{background:linear-gradient(180deg,var(--accent-2),var(--accent));
             color:var(--on-accent);box-shadow:0 8px 22px rgba(232,163,61,.28)}
.btn.primary:hover{background:linear-gradient(180deg,var(--accent-2),var(--accent));
                   filter:brightness(1.05)}
.btn{background:var(--surface-2);border:1px solid var(--hair);color:var(--ink)}
.btn:hover{background:var(--surface)}
.tagpill.b{background:rgba(232,163,61,.16);color:var(--accent)}
a,.link{color:var(--accent)}
/* ⚠️ `.link` 는 색만 정해 뒀다. `<button class="link">` 는 그래서 브라우저
   기본 단추 여백(1px 6px)과 테두리를 그대로 달고 나온다 — 눈금에도 없고
   높이도 24px 밖에 안 됐다. 글처럼 보이려면 단추 껍데기를 벗겨야 한다. */
button.link{background:none;border:0;padding:0;font:inherit;cursor:pointer;
  text-align:inherit;text-decoration:underline;text-underline-offset:2px}

/* 진행 중 채움도 앰버 계열로 */
.btn:not(.primary)[data-state]::after{background:rgba(232,163,61,.18)}

/* ── 하단 탭바 — 바닥에 붙이지 않고 띄운다 ─────────────── */
@media (max-width:820px){
  .tabbar{
    left:var(--s4);right:var(--s4);bottom:calc(var(--s4) + env(safe-area-inset-bottom,0px));
    padding:var(--s2);border-radius:var(--r-full);
    background:var(--surface);border:1px solid var(--hair);
    box-shadow:var(--glow);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur);
  }
  /* 로그인 CTA 와 같은 앰버 — 밝은 쪽을 위로 두어야 먹색 글씨가 읽힌다 */
  .tabbar .tabind{top:var(--s2);bottom:var(--s2);
    background:linear-gradient(180deg,var(--accent-2),var(--accent))}
  .tabbar button.on{color:var(--on-accent)}
  /* ⚠️ 탭바 높이만 비우면 모자란다. 그 위에 카카오 상담 단추가 떠 있어서
     맨 끝까지 내리면 마지막 문단이 단추에 깔린다 — 실제로 안내문이 가려졌다.
     탭바 + 단추가 뜬 높이(--s6) + 단추 높이 + 숨 쉴 자리(--s3). */
  main{padding-bottom:calc(var(--tabbar-h) + var(--s6) + var(--support-h) + var(--s3)
       + env(safe-area-inset-bottom,0px))}
}

/* ── 입력란 ──────────────────────────────────────────────── */
input,select,textarea{background:var(--surface-2);border:1px solid var(--hair);color:var(--ink)}
input:focus,select:focus,textarea:focus{
  border-color:var(--accent);box-shadow:0 0 0 3px rgba(232,163,61,.18);outline:none}

/* ── 조직도 노드도 같은 재질 ─────────────────────────────── */
.tbox{background:var(--surface);border:1px solid var(--hair);box-shadow:var(--glow);
      backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur)}
.tbox.more{background:none;border-color:var(--brand);box-shadow:none}

/* ── 등장 ────────────────────────────────────────────────── */
/*
 * ⚠️ 채우기는 `backwards` 다. `both` 로 쓰지 마라 — 그 순간 이 규칙에
 *    걸리는 **모든** 상자가 영구 stacking context 가 된다.
 *
 *    왜: `both` = backwards + forwards 다. 이 키프레임들은 `from` 만
 *    적었으니 forwards 로 붙잡을 끝 상태가 애초에 없는데, 브라우저는
 *    애니메이션이 끝난 뒤에도 그 속성을 계속 붙들어 `transform` 을
 *    `matrix(1,0,0,1,0,0)` 으로 남긴다. 항등행렬이라 눈에는 아무 일도
 *    없지만 `none` 이 아니라서 stacking context 와 containing block 이
 *    생긴다 — 그 안의 `position:absolute` 메뉴는 z-index 를 아무리 올려도
 *    그 상자 밖으로 못 올라간다.
 *    실제로 감사 로그·출금 화면에서 드롭다운이 아래 표 밑으로 깔렸다.
 *    `backwards` 는 지연 동안 `from` 을 붙잡아 주는(깜빡임 방지) 쪽이라
 *    그건 그대로 필요하고, 끝나면 `transform:none` 으로 깨끗이 돌아간다.
 *    `scripts/audit-spacing.mjs` 의 `겹침가둠` 검사가 이걸 지킨다.
 */
.sec,.card,.list,.prog,.trio,.stats{animation:riseIn var(--t-slow) var(--e-out) backwards}
@keyframes riseIn{from{opacity:0;transform:translateY(10px)}}

/* ── 액센트를 하나로 ───────────────────────────────────────
   ⚠️ `--brand` 를 앰버로 되돌린다. 이 한 줄이 조직도 루트·게이지·시소·
      알림 점·단계 번호까지 전부 따라오게 만든다. 컴포넌트를 하나씩 고치면
      반드시 한 곳을 빠뜨리고, 파란 조각이 남아 "덜 만든 화면" 이 된다. */
:root,:root[data-theme="dark"],:root[data-theme="system"],:root[data-theme="light"]{
  --brand:var(--accent); --brand-ink:var(--accent-2);
  --brand-bg:rgba(232,163,61,.14);
}
/* 앰버 면 위에는 흰 글씨가 읽히지 않는다 — 먹색을 얹는다 */
.tbox.root,.slot.on,.noti .n.new .ic,.step.done .no,.step.now .no,
.shell.drawer .side nav button.on{color:var(--on-accent)}
/*
 * ⚠️ 상자 **안쪽 줄까지** 같이 뒤집어야 한다. 이름만 먹색으로 바꾸고
 *    아이디·등급·실적 줄을 흰색으로 두면 금색 면 위에서 1.2~1.8:1 이 된다 —
 *    글자가 있다는 것만 겨우 보이는 수준이고, 실제로 그렇게 나가 있었다.
 *    먹색으로 바꾸면 4.6~6.8:1 이 된다 (11px 작은 글씨라 4.5:1 이 최소선).
 * ⚠️ 투명도를 더 낮추지 마라. 금색 면은 그라데이션이라 **진한 쪽
 *    (`--fill-2`)** 이 최악이고, 거기서 4.5:1 을 못 넘으면 실패다.
 */
.tbox.root .c{color:var(--on-accent-3)}
.tbox.root .lr{color:var(--on-accent-2)}
.tbox.root .lr b,.tbox.root .n{color:var(--on-accent)}
/* 인정·상태 딱지도 마찬가지 — 흰 바탕에 흰 글씨였다 */
.tbox.root .st.rec,.tbox.root .st.mut,.tbox.root .st.no{
  background:var(--on-accent-bg);color:var(--on-accent)}
.warnbox,.guide{background:var(--brand-bg);color:var(--ink);border:1px solid var(--hair)}
.warnbox b,.guide b{color:var(--accent-2)}
/* ⚠️ 시소 다리 색은 아래 "면 채우기" 블록에서 정한다. 여기서 또 칠하면
   둘 중 하나만 고치게 된다. */

/* ── 상단 헤더도 같은 재질 ───────────────────────────────── */
.topbar,.apphd,header.hd{background:var(--surface-2);border-bottom:1px solid var(--hair);
  backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur)}

/* ═══════════════════════════════════════════════════════════
   인증 화면 모션 — 레퍼런스 영상 두 편을 그대로 옮긴 자리

   ① 카드 뒤집기 (Login form V7)
      화면을 갈아끼우지 않는다. 나가는 면이 Y축으로 접히고,
      들어오는 면이 반대편에서 펴진다. 같은 카드가 돌아선 것처럼 보인다.
   ② 숫자 스프링 입력 + 검증 → 완료 (Glassy OTP)
   ═══════════════════════════════════════════════════════════ */
.login{perspective:1200px}
.login .box{transform-origin:50% 50%;will-change:transform}
.login.flipout .box{animation:flipOut .30s var(--e-inout) forwards}
.login.flipin  .box{animation:flipIn  .44s var(--e-out) backwards}
@keyframes flipOut{to{transform:perspective(1200px) rotateY(-92deg) scale(.96);opacity:.15}}
@keyframes flipIn{from{transform:perspective(1200px) rotateY(92deg) scale(.96);opacity:.15}}

/* ── OTP 칸 ────────────────────────────────────────────────
   ⚠️ 진짜 <input> 을 지우지 마라. 칸은 보여 주기만 하고 입력·붙여넣기·
      문자 자동완성(one-time-code)은 전부 원래 input 이 받는다.
      칸만 만들면 iOS 의 자동 입력이 죽는다. */
.otpwrap{position:relative;margin:var(--s5) 0 var(--s4)}
.otpwrap input{position:absolute;inset:0;width:100%;height:100%;
  opacity:0;border:0;background:none;color:transparent;caret-color:transparent;
  font-size:var(--fs-2xl);letter-spacing:2em;z-index:2;cursor:pointer}
.otpwrap input:focus{box-shadow:none;outline:none}
.otpboxes{display:flex;gap:var(--s2);justify-content:center;pointer-events:none}
.otpboxes i{flex:1;max-width:52px;aspect-ratio:3/4;border-radius:var(--r-sm);
  display:grid;place-items:center;font-style:normal;
  font-size:var(--fs-xl);font-weight:var(--fw-bold);font-variant-numeric:tabular-nums;
  background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.14);color:#fff;
  transition:border-color var(--t-base) var(--e-out),box-shadow var(--t-base) var(--e-out),
             background var(--t-base) var(--e-out)}
.otpboxes i.on{border-color:var(--accent-2);background:rgba(232,163,61,.10)}
.otpwrap input:focus + .otpboxes i.caret{border-color:var(--accent-2);
  box-shadow:0 0 0 3px rgba(232,163,61,.20)}
.otpboxes i span{display:inline-block}
.otpboxes i span.pop{animation:otpPop .48s var(--e-spring) backwards}
@keyframes otpPop{
  0%{opacity:0;transform:translateY(-1.1em) scale(.35) rotate(-14deg)}
  60%{opacity:1;transform:translateY(.06em) scale(1.14) rotate(3deg)}
  100%{opacity:1;transform:none}}
/* 틀렸을 때 — 좌우로 한 번 털어낸다 */
.otpwrap.bad .otpboxes i{border-color:var(--bad)}
.otpwrap.bad{animation:shake .38s var(--e-inout)}
@keyframes shake{0%,100%{transform:translateX(0)}20%{transform:translateX(-7px)}
  45%{transform:translateX(6px)}70%{transform:translateX(-3px)}}

/* ── 검증 완료 ─────────────────────────────────────────────
   체크가 튀어 들어오고 링이 두 번만 퍼진다. 무한 반복하면
   '아직 처리 중인가' 로 읽힌다 — 끝난 것은 끝난 표정을 지어야 한다. */
.verified{display:grid;place-items:center;gap:var(--s4);padding:var(--s6) 0;text-align:center}
.verified .ring{position:relative;width:96px;height:96px;display:grid;place-items:center}
.verified .ring::after{content:"";position:absolute;inset:6px;border-radius:var(--r-full);
  border:2px solid var(--ok);opacity:0;animation:okPulse 1.6s var(--e-out) 2}
@keyframes okPulse{0%{transform:scale(.7);opacity:.8}100%{transform:scale(1.5);opacity:0}}
.verified .mark{width:64px;height:64px;border-radius:var(--r-md);display:grid;place-items:center;
  background:rgba(75,189,136,.14);border:1px solid var(--ok);
  animation:okPop .5s var(--e-spring) backwards}
@keyframes okPop{from{transform:scale(.3);opacity:0}}
.verified svg{width:32px;height:32px}
.verified path{stroke:var(--ok);stroke-width:3.2;fill:none;
  stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:30;
  animation:okDraw .45s .18s var(--e-out) backwards}
@keyframes okDraw{from{stroke-dashoffset:30}}
.verified h1{color:#fff;margin:0}
.verified h1 em{font-style:normal;color:var(--ok)}
.verified p{margin:0;color:#9aa4b8;font-size:var(--fs-md)}
/* 완료되면 버튼도 초록으로 — 버튼이 사라지지 않고 그대로 변한다 */
.login .btn.primary[data-state="done"]{background:var(--ok);color:#fff}

/* ═══════════════════════════════════════════════════════════
   로그인 카드 — 레퍼런스 영상(Login form V7)을 그대로 옮긴 자리

   모서리 둘(좌상·우하)이 45° 로 잘린 유리판이다. 잘린 면에는 테두리가
   따라붙어야 하는데 `clip-path` 는 border 를 함께 자른다 —
   그래서 **두 겹**으로 만든다: 바깥층이 테두리 색, 안층이 1px 안쪽 유리.
   ═══════════════════════════════════════════════════════════ */
.login .box{
  --cutSize:38px;
  /* 조각과 카드 사이에 보이는 대각선 틈 */
  --seam:8px;
  /* 잘라낼 '빗변까지의 수직거리' = 변 × cos45 + 틈.
     ⚠️ 조각은 제자리에 두고 **카드 쪽만 더 깊게 판다.** 둘을 같은 값으로 두면
        빗변이 딱 붙어 틈이 사라진다. */
  --cutD:calc(var(--cutSize) * 0.7071 + var(--seam));
  /* 좌상단·우하단만 45°로 잘라내는 마스크. 나머지 두 모서리의 라운드는 살아남는다.
     ⚠️ clip-path 로 자르면 border-radius 가 통째로 무시돼 네 모서리가 전부 각진다 —
        그래서 잘린 곳이 아닌 우상단·좌하단까지 뾰족해졌던 것이다. */
  --notch:linear-gradient(135deg, transparent 0 var(--cutD), #000 var(--cutD)),
          linear-gradient(315deg, transparent 0 var(--cutD), #000 var(--cutD));
  position:relative; width:100%; max-width:376px;
  padding:var(--s8) var(--s6) var(--s6);
  background:none; border:0; box-shadow:none;
  animation:cardIn .7s var(--e-out) backwards;
}
@keyframes cardIn{from{opacity:0;transform:translateY(16px) scale(.97)}}

/* 판 — 바깥층이 테두리, ::after 가 1px 안쪽 유리면 */
.login .pane{position:absolute;inset:0;z-index:0;border-radius:var(--r-lg);
  background:linear-gradient(140deg,
    var(--edge-hi) 0%, var(--edge-lo) 32%, var(--edge-lo) 64%, var(--edge-mid) 100%);
  -webkit-mask:var(--notch);mask:var(--notch);
  -webkit-mask-composite:source-in;mask-composite:intersect;
  filter:drop-shadow(var(--card-sh))}
/* 유리면 — 위에서 들어온 빛이 면을 타고 흐르고, 아래쪽엔 두께의 그늘이 진다 */
.login .pane::after{content:"";position:absolute;inset:1px;
  border-radius:calc(var(--r-lg) - 1px);
  background:
    linear-gradient(152deg, var(--sheen) 0%, transparent 32%),
    linear-gradient(332deg, var(--shade) 0%, transparent 28%),
    var(--surface);
  -webkit-mask:var(--notch);mask:var(--notch);
  -webkit-mask-composite:source-in;mask-composite:intersect}
.login .box > .face{position:relative;z-index:1}
.login .prefsbtn.onlogin{z-index:3}

/* ── 모서리 조각 — 전환의 주인공 ───────────────────────────
   카드에서 잘려나간 노치를 메우는 **직각삼각형 두 개**다.
   전환하면 둘이 가운데로 모여 빗변끼리 맞붙어 정사각형이 되고
   (그래서 가운데에 대각선 이음매가 생긴다), 다시 제자리로 돌아간다.

   ⚠️ clip-path 는 border 까지 자른다. 빗변의 이음매는 테두리가 아니라
      배경 그라데이션의 밝은 끝으로 만든다. */
.login .corner{position:absolute;width:var(--cutSize);height:var(--cutSize);z-index:2;
  overflow:visible;
  /* ⚠️ 평소에는 잘린 자리에 **정확히** 들어앉는다. 조금이라도 밀어내면
     조각의 두 변이 카드의 위·왼쪽 변과 어긋나 잘린 자국이 맞지 않는다. */
  --gap:0px;
  transition:transform .9s var(--e-out)}
/* ⚠️ border-radius + clip-path 로는 못 만든다 — 잘린 빗변의 두 끝이 뾰족하게 남는다.
   stroke-linejoin:round 로 부풀리는 것도 안 된다 — 45° 꼭짓점의 라운드가
   빗변을 거의 다 먹어 버려 삼각형이 아니라 덩어리가 된다.
   세 꼭짓점을 각각 **호(arc)로 직접** 그린다. 45° 꼭짓점의 접선거리는
   r/tan(22.5°) = 2.41r 로, 90° 꼭짓점(r)보다 훨씬 길다. */
/* ⚠️ 조각은 카드에서 떨어져 나온 같은 판이다. 잘 보이라고 다른 색을 칠하면
   다른 재질로 읽힌다. 면·테두리를 카드와 똑같이 두고, 구분은 그림자와
   떨어진 간격(--gap)으로만 준다. */
.login .corner path{stroke:var(--edge-mid);stroke-width:1;
  vector-effect:non-scaling-stroke;filter:drop-shadow(var(--piece-sh2))}

.login .corner.tl{left:0;top:0;
  transform:translate(calc(-1 * var(--gap)),calc(-1 * var(--gap)))}
.login .corner.br{right:0;bottom:0;
  transform:translate(var(--gap),var(--gap))}
/* 모인 상태 — 거리(--mx/--my)는 카드 크기에서 계산해 lib.js 가 넣는다 */
.login.morph .corner.tl{transform:translate(var(--mx,0),var(--my,0))}
.login.morph .corner.br{transform:translate(calc(-1 * var(--mx,0)),calc(-1 * var(--my,0)))}
/* 되돌아올 위치로 순간이동시킬 때만 — 애니메이션 없이 */
.login.nomotion .corner{transition:none}

.login.morph .face{animation:faceOut .46s var(--e-inout) forwards}
.login.morphin .face{animation:faceIn .72s var(--e-out) .1s backwards}
@keyframes faceOut{to{opacity:0;transform:scale(.97) translateY(-6px);filter:blur(5px)}}
@keyframes faceIn{from{opacity:0;transform:scale(1.02) translateY(10px);filter:blur(6px)}}

/* ── 타이포 ───────────────────────────────────────────────── */
.login h1{font-size:var(--fs-2xl);font-weight:var(--fw-bold);letter-spacing:var(--ls-title);
  margin:0 0 var(--s1);color:var(--card-ink)}
.login h1 em{font-style:normal;color:var(--accent-2)}
.login .sub{margin:0 0 var(--s6);color:var(--card-ink-2);font-size:var(--fs-sm)}

/* ── 입력란 — 라벨 위, 아이콘 안쪽 ─────────────────────────── */
.login .fld{display:block;margin:0 0 var(--s4)}
.login .fld > span{display:block;margin-bottom:var(--s2);
  font-size:var(--fs-xs);font-weight:var(--fw-medium);color:var(--card-ink-2);letter-spacing:.01em}
.login .ctl{position:relative;display:block}
.login .ctl .ic{position:absolute;left:var(--s3);top:50%;transform:translateY(-50%);
  width:17px;height:17px;stroke:var(--card-ink-3);fill:none;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round;pointer-events:none;
  transition:stroke var(--t-base) var(--e-out)}
.login .ctl input{width:100%;margin:0;padding:var(--s3) var(--s4) var(--s3) 40px;
  border-radius:10px;font-size:var(--fs-md);color:var(--card-ink);
  background:var(--ground);border:1px solid var(--hair);
  transition:border-color var(--t-base) var(--e-out),box-shadow var(--t-base) var(--e-out),
             background var(--t-base) var(--e-out)}
.login .ctl input::placeholder{color:var(--card-ink-3)}
.login .ctl input:focus{outline:none;background:var(--ground);
  border-color:var(--accent-2);box-shadow:0 0 0 3px rgba(232,163,61,.18)}
.login .ctl:focus-within .ic{stroke:var(--accent-2)}
.login .eye{position:absolute;right:var(--s2);top:50%;transform:translateY(-50%);
  background:none;border:0;padding:var(--s2);cursor:pointer;line-height:0;
  color:var(--card-ink-3);transition:color var(--t-fast)}
.login .eye:hover,.login .eye[aria-pressed="true"]{color:var(--accent-2)}
.login .eye svg{width:17px;height:17px;stroke:currentColor;fill:none;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round}

/* 들어갈 자리 — 좌/우 두 단추.
   ⚠️ 못 고르는 쪽을 **감추지 마라.** 없어 보이면 "고장났다" 로 읽힌다 —
      잠그고 **왜 잠겼는지**를 단추 안에 적는다. 잠긴 단추는 흐리게 두되
      글자는 읽히는 밝기로 남긴다(읽으라고 적어 둔 문장이다). */
.login .legpick{display:grid;grid-template-columns:1fr 1fr;gap:var(--s2);margin-bottom:var(--s4)}
.login .legbtn{display:flex;flex-direction:column;align-items:center;gap:3px;margin:0;
  padding:var(--s3) var(--s2);border-radius:10px;cursor:pointer;text-align:center;
  font-family:var(--font);font-size:var(--fs-sm);color:var(--card-ink);
  background:var(--ground);border:1px solid var(--hair);
  transition:border-color var(--t-base) var(--e-out),box-shadow var(--t-base) var(--e-out),
             background var(--t-base) var(--e-out),color var(--t-base) var(--e-out)}
.login .legbtn b{font-weight:var(--fw-semi);letter-spacing:.01em}
.login .legbtn .why{font-size:var(--fs-2xs);color:var(--card-ink-3);line-height:1.35}
.login .legbtn .why:empty{display:none}
.login .legbtn:not(:disabled):hover{border-color:var(--accent-2)}
.login .legbtn:focus-visible{outline:2px solid var(--accent-2);outline-offset:2px}
.login .legbtn.on{border-color:var(--accent-2);background:var(--accent-2);color:#fff;
  box-shadow:0 0 0 3px rgba(232,163,61,.18)}
.login .legbtn.on .why{color:#fff;opacity:.9}
.login .legbtn:disabled{cursor:not-allowed;opacity:.62;box-shadow:none}

.login .fldrow{display:flex;align-items:center;justify-content:space-between;
  gap:var(--s3);margin:calc(-1 * var(--s1)) 0 var(--s5);flex-wrap:wrap}
.login .chk{display:flex;align-items:center;gap:var(--s2);margin:0;cursor:pointer;
  font-size:var(--fs-xs);color:var(--card-ink-2)}
.login .chk input{appearance:none;-webkit-appearance:none;width:16px;height:16px;margin:0;flex:none;
  border-radius:5px;border:1px solid var(--hair);background:var(--ground);
  cursor:pointer;position:relative;transition:background var(--t-fast),border-color var(--t-fast)}
.login .chk input:checked{background:var(--accent-2);border-color:var(--accent-2)}
.login .chk input:checked::after{content:"";position:absolute;left:5px;top:2px;
  width:4px;height:8px;border:solid #2a1a05;border-width:0 2px 2px 0;transform:rotate(42deg)}
.login .chk input:focus-visible{outline:2px solid var(--accent-2);outline-offset:2px}

/* ── CTA — 노란 단색 + 화살표 ─────────────────────────────── */
.login .btn.primary.cta{display:flex;align-items:center;justify-content:center;gap:var(--s2);
  width:100%;padding:var(--s4);border-radius:10px;margin-top:0;
  font-size:var(--fs-md);font-weight:var(--fw-bold);
  background:linear-gradient(180deg,#ffd97a,#f0b93c);color:#2a1a05;
  box-shadow:0 10px 30px rgba(240,185,60,.30);
  transition:transform var(--t-fast) var(--e-spring),box-shadow var(--t-base),filter var(--t-fast)}
.login .btn.primary.cta:hover{filter:brightness(1.05);box-shadow:0 12px 34px rgba(240,185,60,.42)}
.login .btn.primary.cta:active{transform:scale(.985)}
.login .btn.primary.cta svg{width:17px;height:17px;stroke:currentColor;fill:none;
  stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;
  transition:transform var(--t-base) var(--e-out)}
.login .btn.primary.cta:hover svg{transform:translateX(3px)}

.login .hint{margin-top:var(--s5);padding:var(--s3) 0 0;border-radius:0;
  background:none;border:0;border-top:1px solid var(--hair);
  font-size:var(--fs-2xs);color:var(--card-ink-3);line-height:1.7;text-align:center}
.login .hint b{color:var(--card-ink-2);font-weight:var(--fw-semi)}
.login .msg{margin-top:var(--s3);font-size:var(--fs-sm)}

/* 좁은 화면에서 모서리 조각이 화면 밖으로 삐져나가지 않게 */
@media (max-width:420px){
  .login{padding:var(--s5)}
  .login .box{--cutSize:30px;padding:var(--s6) var(--s5)}
  /* ⚠️ 조각 크기를 따로 박지 마라. --cutSize 와 어긋나면 가운데에서 맞붙지 않는다
     (조각은 --cutSize 로 그려지는데 이동 거리는 --cutSize 로 계산되기 때문). */
}

/* ── 로그인 성공 연출 ──────────────────────────────────────
   버튼이 채워지고 → 카드가 비며 섬광 → 앱이 들어온다.
   레퍼런스의 전환은 "Sign In ↔ Sign Up" 링크에서 일어나는데,
   우리 로그인엔 그 토글이 없으므로 **로그인 성공**을 그 자리로 삼는다. */
.login .btn.primary.cta[data-state="run"]{filter:none}
.login .btn.primary.cta[data-state="done"]{
  background:linear-gradient(180deg,#5ee9b5,var(--ok));color:#052617;
  box-shadow:0 10px 30px rgba(75,189,136,.34)}
.login .btn.primary.cta[data-state]::after{background:rgba(255,255,255,.28)}
/* 실패하면 버튼을 한 번 턴다 — 어디가 틀렸는지 눈이 바로 간다 */
.shakeNo{animation:shakeNo .42s var(--e-inout)}
@keyframes shakeNo{0%,100%{transform:translateX(0)}18%{transform:translateX(-8px)}
  42%{transform:translateX(7px)}68%{transform:translateX(-4px)}86%{transform:translateX(2px)}}
/* 앱 등장 — 카드가 사라진 자리에서 위로 차오른다 */
/* ⚠️ `backwards` — `both` 면 끝난 뒤에도 transform·filter 를 붙들어
      `#appView` 가 영구 stacking context 가 된다 (위 riseIn 주석 참고). */
.appin{animation:appIn .6s var(--e-out) backwards}
@keyframes appIn{from{opacity:0;transform:translateY(14px) scale(.995);filter:blur(4px)}}

/* ═══════════════════════════════════════════════════════════
   전 화면 모션 — 레퍼런스 영상들의 공통 문법
   ⚠️ 여기 있는 것 말고 화면 코드에서 따로 애니메이션을 만들지 마라.
      지속시간·이징은 위의 --t-* / --e-* 만 쓴다.
   ⚠️ 움직임 줄이기 설정은 위쪽 @media (prefers-reduced-motion) 의
      `!important` 가 전부 꺼 준다. 아래 규칙은 그 뒤에 와도 안전하다.
   ═══════════════════════════════════════════════════════════ */

/* ── 1. 탭을 바꾸면 그 화면의 조각들이 차례로 올라온다 ──────
   한꺼번에 나타나면 "번쩍" 하고 끝나 눈이 어디에 붙을지 모른다.
   40ms 씩 어긋내면 위에서 아래로 읽히는 순서가 생긴다.
   ⚠️ 8번째부터는 지연을 더 늘리지 않는다. 긴 화면에서 마지막 카드가
      1초 뒤에 오면 "느린 앱" 으로 느껴진다. */
section.on > *{animation:riseIn var(--t-slow) var(--e-out) backwards}
section.on > *:nth-child(1){animation-delay:0ms}
section.on > *:nth-child(2){animation-delay:45ms}
section.on > *:nth-child(3){animation-delay:90ms}
section.on > *:nth-child(4){animation-delay:135ms}
section.on > *:nth-child(5){animation-delay:180ms}
section.on > *:nth-child(6){animation-delay:215ms}
section.on > *:nth-child(n+7){animation-delay:250ms}

/* ── 2. 목록 줄도 같은 방식으로 ──────────────────────────────
   목록은 JS 가 다시 그리므로 새로 그릴 때마다 저절로 다시 돈다. */
/* ⚠️ `backwards` — `both` 면 **목록의 모든 줄과 표의 모든 행**이 각각
      영구 stacking context 가 된다. 줄 안에 드롭다운이 있으면 그 줄
      밖으로 못 나온다 (위 riseIn 주석 참고). */
.list .li,.tblwrap tbody tr{animation:rowIn var(--t-base) var(--e-out) backwards}
@keyframes rowIn{from{opacity:0;transform:translateY(6px)}}
.list .li:nth-child(1),.tblwrap tbody tr:nth-child(1){animation-delay:0ms}
.list .li:nth-child(2),.tblwrap tbody tr:nth-child(2){animation-delay:30ms}
.list .li:nth-child(3),.tblwrap tbody tr:nth-child(3){animation-delay:60ms}
.list .li:nth-child(4),.tblwrap tbody tr:nth-child(4){animation-delay:90ms}
.list .li:nth-child(5),.tblwrap tbody tr:nth-child(5){animation-delay:120ms}
.list .li:nth-child(6),.tblwrap tbody tr:nth-child(6){animation-delay:150ms}
.list .li:nth-child(n+7),.tblwrap tbody tr:nth-child(n+7){animation-delay:175ms}

/* 줄에 손이 닿으면 살짝 뜬다 — "누를 수 있는 것" 이라는 신호 */
.list .li{transition:background var(--t-fast) var(--e-out)}
.list .li:hover{background:var(--surface-2)}

/* ── 3. 누르는 느낌 ──────────────────────────────────────────
   ⚠️ `.btn[data-state]` 은 진행 상태를 스스로 그린다. 여기서 transform 을
      얹으면 진행 중에도 눌린 채로 굳는다. 상태 없는 것만 잡는다. */
.btn:not([data-state]):active,.quick button:active,
.seg button:active,.tagpill:active{transform:scale(.97)}
.btn:not([data-state]),.quick button,.seg button{
  transition:transform var(--t-fast) var(--e-spring),
             background var(--t-fast) var(--e-out),
             color var(--t-fast) var(--e-out),
             border-color var(--t-fast) var(--e-out)}

/* 세그먼트 — 고른 칸이 톡 올라온다 */
.seg button.on,.seg button[aria-selected="true"]{
  animation:segPop var(--t-base) var(--e-spring)}
@keyframes segPop{from{transform:scale(.9)}}

/* 바로가기 버튼 — 아이콘이 먼저 반응한다 */
.quick svg{transition:transform var(--t-base) var(--e-spring)}
.quick button:hover svg{transform:translateY(-2px) scale(1.08)}

/* ── 4. 조직도 노드 ──────────────────────────────────────────
   그릴 때마다 제자리에서 톡 튀어 오른다. 트리가 한 번에 통째로
   나타나면 어디가 새로 생긴 가지인지 알 수 없다. */
/* ⚠️ `backwards` — `both` 면 조직도의 **모든 상자**가 등장 뒤에도 항등
      transform 을 쥐고 있어 각각 겹침을 가두는 상자가 된다. 상자 위에
      무언가(연결선·말풍선)를 겹쳐 그릴 때 그 상자 밖으로 못 나온다.
      (base.css 의 riseIn 주석 참고) */
.tbox{animation:nodePop var(--t-base) var(--e-spring) backwards;
      transition:transform var(--t-fast) var(--e-spring),box-shadow var(--t-fast) var(--e-out)}
@keyframes nodePop{from{opacity:0;transform:scale(.88)}}
.tbox:hover{transform:translateY(-2px)}

/* ── 5. 종·설정 같은 아이콘 버튼 ─────────────────────────────── */
.bellbtn svg,.prefsbtn svg,.menubtn svg{
  transition:transform var(--t-base) var(--e-spring)}
.bellbtn:hover svg{transform:rotate(-12deg) scale(1.08)}
.prefsbtn:hover svg{transform:rotate(45deg)}
.menubtn:hover svg{transform:scale(1.1)}
/* 안 읽은 알림이 있으면 점이 숨쉰다 — 한 번 보고 나면 멈춰야 하므로
   `.hide` 가 붙는 순간 알아서 사라진다 */
.bellbtn .dot:not(.hide){animation:dotPulse 2.4s var(--e-inout) infinite}
@keyframes dotPulse{0%,100%{transform:scale(1)}50%{transform:scale(1.35)}}

/* ── 6. 설정 패널 ────────────────────────────────────────────
   눌린 자리(오른쪽 위)에서 펼쳐져야 어디서 나온 건지 보인다 */
.prefs:not([hidden]){animation:panelIn var(--t-base) var(--e-spring) backwards;
                     transform-origin:top right}
@keyframes panelIn{from{opacity:0;transform:scale(.94) translateY(-6px)}}

/* ── 7. 게이지·막대 ──────────────────────────────────────────
   0 에서 차오르는 게 보여야 "얼마나" 가 몸으로 읽힌다 */
.prog > div,.bar > div{transition:width var(--t-slow) var(--e-out)}

/* ── 8. PC 사이드 표시자도 같은 스프링으로 ───────────────────── */
.side nav .navind{transition:transform var(--t-base) var(--e-spring),
                             height var(--t-base) var(--e-spring),
                             opacity var(--t-base) var(--e-out)}
.side nav button{transition:color var(--t-fast) var(--e-out)}

/* ── 9. 입력란 — 초점이 가면 살짝 떠오른다 ───────────────────── */
input,select,textarea{transition:border-color var(--t-fast) var(--e-out),
                                 box-shadow var(--t-fast) var(--e-out),
                                 background var(--t-fast) var(--e-out)}

/* ── 예산 막대 색 ────────────────────────────────────────────
   ⚠️ 여기 한 곳만 고치면 막대와 아래 범례가 같이 바뀐다. 색을 HTML 에
      직접 박으면 반드시 한쪽만 고치게 되고, 범례와 막대가 어긋난다.
   앰버 한 계열의 명도 단계 — 파란 조각이 하나라도 남으면 "덜 만든 화면" 이 된다. */
:root,:root[data-theme="light"],:root[data-theme="dark"],:root[data-theme="system"]{
  --bud-1:#b0740f; --bud-2:#d89a20; --bud-3:#f0b93c; --bud-4:#ffdd9a; --bud-5:#7a4e06;
}

/* ── 수당 조정 (52단계) ──────────────────────────────────────
   부호는 색으로도 말한다 — 차감은 빨강, 추가는 초록. 표·통계·미리보기에서 같은 클래스다. */
.neg{color:var(--bad)} .pos{color:var(--ok)} .v .warn,b.warn{color:var(--warn)}
td.neg,td.pos{font-weight:var(--fw-semi)}
.warnbox .prevgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:var(--s3);margin-top:var(--s2)}
.prevgrid .k{display:block;font-size:var(--fs-2xs);color:var(--ink-3)}
.prevgrid .v{font-size:var(--fs-sm);color:var(--ink);font-variant-numeric:tabular-nums}
.warnbox .prevgrid b{color:var(--ink)} .warnbox .prevgrid b.neg{color:var(--bad)}
.dlgbody p{margin:0 0 var(--s2)} .dlgbody p.sub{font-size:var(--fs-xs);color:var(--ink-3)}
#ajDir button.on[data-dir="MINUS"]{color:var(--bad)} #ajDir button.on[data-dir="PLUS"]{color:var(--ok)}

/* ── 출금 가능 시간 (55단계) ────────────────────────────────── */
.daypick{display:inline-flex;flex-wrap:wrap;gap:var(--s2) var(--s3)}
.wwblock{padding:var(--s3);border:1px solid var(--line);border-radius:var(--r-sm);margin:var(--s2) 0}
.wwblock input.wwfrom,.wwblock input.wwto{width:7ch;font-family:var(--mono)}
.wwnote{margin-top:var(--s3)}

/* 일별 수당(57단계) — 0 인 칸은 점으로, 눈이 숫자 있는 칸만 밟게 */
td.mutc{color:var(--ink-3)}

/* ── 보상플랜 한눈에 보기 (48단계) ───────────────────────────
   재원 막대 + 공통 규칙 + 수당 카드. 색은 위의 --bud-* 만 쓴다. */
.planov h3{font-size:var(--fs-lg);margin:0 0 var(--s3)}
.planov .kv{grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}
.budline{display:flex;height:var(--s5);border-radius:var(--r-full);overflow:hidden;background:var(--bg-3);gap:var(--s0)}
.budline .seg{display:block;min-width:var(--s1)}
.budlegend{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s4);margin-top:var(--s3);font-size:var(--fs-sm);color:var(--ink-2)}
.budlegend span{display:inline-flex;align-items:center;gap:var(--s2)}
.budlegend i{width:var(--s3);height:var(--s3);border-radius:var(--s0);flex:none}
.budlegend .out i{background:transparent;box-shadow:inset 0 0 0 1px var(--ink-3)}
.budlegend b{font-variant-numeric:tabular-nums}
.bonusgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:var(--s3)}
.bonuscard{background:var(--bg-2);border-radius:var(--r-lg);padding:var(--s4);min-width:0}
.bonuscard header{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;margin-bottom:var(--s3)}
.bonuscard header h3{margin:0;flex:1 1 auto;min-width:0}
.bonuscard dl{display:grid;grid-template-columns:auto 1fr;gap:var(--s2) var(--s3);margin:0;font-size:var(--fs-sm)}
.bonuscard dt{color:var(--ink-3);white-space:nowrap}
.bonuscard dd{margin:0;color:var(--ink);min-width:0;overflow-wrap:anywhere}
.rankcond{margin:var(--s1) 0 0;padding-left:var(--s4);display:grid;gap:var(--s0)}
.planraw{margin-top:var(--s4)}
.planraw summary{cursor:pointer;font-size:var(--fs-sm);color:var(--ink-3);padding:var(--s2) 0}
.planraw[open] summary{margin-bottom:var(--s3)}

/* ── 사이드바 머리 — 이름은 제 줄을 갖는다 ────────────────────
   ⚠️ 216px 안에 이름·알림·로그아웃·설정을 한 줄로 밀어 넣으면 이름이
      "김…" 으로 잘린다. 잘린 이름은 아무 정보도 주지 못한다.
      줄을 나눠서 이름은 온전히, 버튼은 그 아래 한 줄로 둔다. */
@media (min-width:821px){
  .top{flex-wrap:wrap;row-gap:var(--s2)}
  .who{flex:1 0 100%;min-width:0}
}

/* ── 모바일 머리 — 심볼 옆에 바로 이름 ────────────────────────
   심볼을 왼쪽 끝에 두고 이름을 오른쪽 끝으로 밀면 가운데가 텅 빈다.
   붙여 두면 "이 앱 / 이 사람" 한 덩어리로 읽힌다. */
@media (max-width:820px){
  .who{text-align:left}
}

/* ⚠️ 3% 칸은 어느 폭에서도 "센터 3%" 가 들어가지 않는다. 반쯤 잘린 글자는
   아무것도 알려 주지 못하므로 아예 지우고, 아래 범례가 이름을 맡는다.
   그래서 범례는 넓은 화면에서도 늘 보인다. */
.bar > div.tiny{font-size:0}
.barlegend{display:flex}

/* ⚠️ input 은 기본 size 속성 때문에 min-content 폭이 20글자쯤 된다. flex 자식으로
   두고 min-width:0 을 주지 않으면 좁은 화면에서 제 칸 밖으로 삐져나가
   페이지 전체가 옆으로 스크롤된다. (`.top` 에서 겪은 것과 같은 함정) */
input,select,textarea{min-width:0}

/* ═══════════════════════════════════════════════════════════
   면 채우기 색 — 글씨색과 갈라놓는다
   ⚠️ `--accent` 는 **흰 바탕 위의 글씨**가 읽히도록 어둡게 내린 앰버다
      (라이트 `#a86a10`). 그걸 면 채우기에 그대로 쓰면 갈색으로 보인다.
      탭바 알약·조직도 루트·사이드 표시자처럼 **면으로 깔리는 것**은
      아래 `--fill` 을 쓴다. 로그인 CTA 가 쓰던 바로 그 금색이다.
   ⚠️ 이 위에 흰 글씨를 얹지 마라. 금색은 밝아서 흰 글씨가 안 읽힌다.
      먹색(`--on-accent`)을 얹는다.
   ⚠️ 라이트·다크가 같은 값이다. 금색은 검은 바탕에서도 흰 바탕에서도
      같은 밝기로 읽힌다 — 테마마다 다른 금색을 쓰면 두 화면이 다른 앱처럼 보인다.
   ═══════════════════════════════════════════════════════════ */
:root,:root[data-theme="light"],:root[data-theme="dark"],:root[data-theme="system"]{
  --fill-1:#ffd97a;                 /* 밝은 쪽 — 위 */
  --fill-2:#f0b93c;                 /* 진한 쪽 — 아래 */
  --fill:linear-gradient(180deg,var(--fill-1),var(--fill-2));
}

/* 로고 심볼 · 사이드 표시자 · 하단 탭바 알약 */
.brand .dot{background:var(--fill);color:var(--on-accent)}
.side nav .navind{background:var(--fill)}
/* ⚠️ 어드민 사이드는 미끄러지는 표시자를 쓰지 않아서 버튼 자기 배경이 그대로
   보인다. 표시자만 금색으로 바꾸면 회원용만 고쳐지고 어드민은 갈색으로 남는다. */
.side nav button.on{background:var(--fill);color:var(--on-accent)}
.tabbar .tabind{background:var(--fill)}
.shell.drawer .side nav button.on{background:var(--fill);color:var(--on-accent)}

/* 주요 버튼 — 로그인 CTA 와 같은 금색으로 통일 */
.btn.primary{background:var(--fill);color:var(--on-accent);
             box-shadow:0 8px 22px rgba(240,185,60,.28)}
.btn.primary:hover{background:var(--fill);filter:brightness(1.05)}

/* 조직도 루트 · 고른 자리 · 단계 번호 · 새 알림 — 전부 같은 금색 면 */
.tbox.root{background:var(--fill);color:var(--on-accent)}
.slot.on{background:var(--fill);color:var(--on-accent);box-shadow:none}
.step.done .no,.step.now .no{background:var(--fill);color:var(--on-accent)}
.noti .n.new .ic{background:var(--fill);color:var(--on-accent)}

/* 게이지·시소 막대도 면이다 */
.prog .track i,.seesaw i span{background:var(--fill)}
label.chk input[type=checkbox],
.card .row.wrap label.chk input[type=checkbox]{accent-color:var(--fill-2)}

/* ⚠️ 시소에서 짧은 다리를 `--warn`(#b45309)으로 칠하지 마라. 액센트가 금색이
   된 지금은 두 다리가 "같은 색의 두 명도" 로 보여서, 어느 쪽이 모자란지가
   아니라 그냥 그라데이션으로 읽힌다. 찬 다리는 금색, 짧은 다리는 흐린 먹색 —
   "저쪽은 아직 안 찼다" 가 한눈에 들어온다. 숫자는 그대로 경고색을 쓴다. */
.seesaw i.weak span{background:var(--ink-3)}

/* ═══════════════════════════════════════════════════════════
   서브탭 — 한 화면을 여러 장으로
   하단 탭바와 같은 언어: 고른 칸 뒤로 금색 알약이 미끄러진다.
   ⚠️ 좁은 화면에서 장이 네 개를 넘으면 글자가 눌린다. 줄바꿈 대신
      가로 스크롤로 흘린다 — 줄이 두 줄이 되면 제목과 본문 사이가
      뚝 끊겨 보인다.
   ═══════════════════════════════════════════════════════════ */
.subnav{position:relative;display:flex;gap:var(--s1);
  margin:var(--s5) 0 var(--s6);padding:var(--s1);
  background:var(--surface-2);border:1px solid var(--hair);border-radius:var(--r-full);
  overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.subnav::-webkit-scrollbar{display:none}
.subnav button{position:relative;z-index:1;flex:1 0 auto;white-space:nowrap;
  background:none;border:0;border-radius:var(--r-full);cursor:pointer;
  padding:var(--s2) var(--s4);font-family:var(--font);font-size:var(--fs-sm);
  font-weight:var(--fw-semi);color:var(--ink-3);letter-spacing:var(--ls-base);
  transition:color var(--t-base) var(--e-out)}
.subnav button:hover{color:var(--ink)}
.subnav button.on{color:var(--on-accent)}
.subnav button:focus-visible{outline:2px solid var(--accent-2);outline-offset:-2px}
/* ⚠️ 표시자는 스크롤되는 상자 안에 있다. `left:0` 은 스크롤 안 한 상태의
   안쪽 끝이고 offsetLeft 도 같은 기준이라 서로 맞는다. position 을 다시
   선언하지 마라 — 탭바에서 겪은 것과 같은 함정이다. */
.subnav .subind{position:absolute;left:0;top:var(--s1);bottom:var(--s1);width:0;z-index:0;
  background:var(--fill);border-radius:var(--r-full);opacity:0;
  transition:transform var(--t-base) var(--e-spring),width var(--t-base) var(--e-out),
             opacity var(--t-base) var(--e-out)}

.subpane{display:none}
.subpane.on{display:block;animation:riseIn var(--t-slow) var(--e-out) backwards}
/* 장 안의 첫 블록은 이미 장 자체가 올라오므로 또 어긋내지 않는다 */
.subpane.on > *{animation:none}

/* 장 하나가 통째로 비었을 때 — 화면이 고장난 게 아니라는 걸 말해 준다.
   ⚠️ `:first-child` 를 빼지 마라. 뜻은 "장의 **첫 블록**이면 위를 안 띄운다"
      인데, 조건 없이 걸면 위에 무언가가 생긴 날 그 사이가 0 이 된다 —
      회원 상세에 회원 목록을 올렸더니 빈 안내가 목록에 딱 붙었다. */
.subpane .empty:first-child{margin-top:0}

/* ── 거르기 줄 ───────────────────────────────────────────────
   ⚠️ 칩을 줄바꿈으로 흘리지 마라. 여덟 개가 두세 줄이 되면 화면 위쪽을
      다 먹어서 정작 결과가 안 보인다. 한 줄로 두고 옆으로 흘린다. */
.filter{margin:var(--s5) 0 var(--s6);display:flex;flex-direction:column;gap:var(--s3)}
.chips,.quickdates{display:flex;gap:var(--s2);overflow-x:auto;
  scrollbar-width:none;-webkit-overflow-scrolling:touch;padding-bottom:var(--s1)}
.chips::-webkit-scrollbar,.quickdates::-webkit-scrollbar{display:none}
.chip{flex:0 0 auto;white-space:nowrap;cursor:pointer;
  background:var(--surface-2);border:1px solid var(--hair);border-radius:var(--r-full);
  padding:var(--s2) var(--s4);font-family:var(--font);font-size:var(--fs-sm);
  font-weight:var(--fw-medium);color:var(--ink-2);
  transition:background var(--t-fast) var(--e-out),color var(--t-fast) var(--e-out),
             border-color var(--t-fast) var(--e-out),transform var(--t-fast) var(--e-spring)}
.chip:hover{color:var(--ink);border-color:var(--ink-3)}
.chip:active{transform:scale(.96)}
.chip.on{background:var(--fill);border-color:transparent;color:var(--on-accent);
         font-weight:var(--fw-semi);animation:segPop var(--t-base) var(--e-spring)}
.chip:focus-visible{outline:2px solid var(--accent-2);outline-offset:2px}
/* 날짜 두 칸 + 초기화를 한 줄에 둔다.
   ⚠️ 이름(시작일/종료일)을 칸 **옆**에 두면 320px 에서 종료일이 화면 밖으로
      나간다. 칸 **위**로 올리면 세 덩이가 한 줄에 다 들어간다.
   ⚠️ `1fr 1fr` 로 두 칸을 같이 늘리지 마라. 날짜 칸은 내용보다 넓어질 이유가
      없는데 늘어나서 가운데가 휑해진다. 내용 폭(auto)으로 두고 남는 자리는
      초기화 앞의 빈 칸이 먹는다. */
.filter .daterow{display:flex;align-items:flex-end;gap:var(--s2);flex-wrap:nowrap}
.filter .daterow label{display:flex;flex-direction:column;gap:var(--s1);margin:0;min-width:0;
  flex:0 1 auto;font-size:var(--fs-2xs);color:var(--ink-3);font-weight:var(--fw-medium)}
.filter .daterow input[type=date]{width:100%;min-width:0;
  font-family:var(--font);font-size:var(--fs-sm);
  padding:var(--s2) var(--s2);border-radius:var(--r-sm)}
.filter .daterow .btn{flex:0 0 auto;margin-left:auto;white-space:nowrap;
  padding:var(--s2) var(--s3);font-size:var(--fs-xs)}
/* 아무것도 안 걸렸으면 초기화는 할 일이 없다 — 지우면 줄이 들썩이니 흐려만 둔다 */
.filter:not(.active) .daterow .btn{opacity:.45;pointer-events:none}
/* 기간이 걸려 있으면 눈에 보여야 한다 — 안 그러면 "왜 이것밖에 없지" 가 된다 */
.filter.active .daterow input[type=date]{border-color:var(--accent);color:var(--ink)}
.note.warn{color:var(--warn)}
@media (max-width:380px){
  /* 아주 좁으면 이름을 빼고 칸만 남긴다 — 날짜 칸 자체가 형식을 말해 준다 */
  .filter .daterow label > span:not(.datebox){display:none}
  .filter .daterow .btn{padding:var(--s2)}
}

/* ── 조직도 확대·축소 ─────────────────────────────────────── */
/* ── 조직도 + 옆에 붙는 회원 카드 ───────────────────────────
 *
 * 넓은 화면은 **옆**, 좁은 화면은 **아래에서 올라오는 판**이다. 좁은 화면에서
 * 옆에 두면 조직도가 손가락 두 개 폭으로 쪼그라들고, 넓은 화면에서 아래를
 * 덮으면 방금 누른 가지가 가려진다 — 그래서 같은 판을 두 자리에 둔다.
 *
 * ⚠️ 판을 `.treebox` **안**에 넣지 마라. 그 상자가 스크롤되는 당사자라
 *    옆으로 끌면 판이 같이 흘러 화면 밖으로 나간다(`.zoomctl` 과 같은 이유).
 * ⚠️ 판이 닫혀 있을 때 자리를 남기지 마라. `.treepane` 은 그냥 flex 라
 *    `.hide` 면 조직도가 폭을 다 쓴다.
 */
.treepane{display:flex;gap:var(--s4);align-items:flex-start}
/* ⚠️ 둘 다 적는다. 배율 조작을 붙이기 **전**에는 `.treebox` 가 직접 자식이고,
   붙은 뒤에는 `.treewrap` 이 그 자리를 넘겨받는다 — 한쪽만 적으면 첫 그림에서
   조직도가 min-content 폭으로 쭈그러든다. */
.treepane > .treewrap,
.treepane > .treebox{flex:1 1 auto;min-width:0}
.treeside{flex:0 0 clamp(240px,30%,320px);background:var(--bg-2);
  border-radius:var(--r-lg);padding:var(--s5);max-height:640px;overflow:auto}
.treeside .orgcard-head{margin-bottom:var(--s4)}
.treeside .orgcard-head .n{font-size:var(--fs-md);font-weight:var(--fw-bold);
  line-height:var(--lh-snug)}
.treeside .orgcard-head .n.dead{text-decoration:line-through;text-decoration-thickness:1px;
  opacity:.7}
.treeside .orgcard-head .c{margin-top:var(--s1);font-size:var(--fs-xs);color:var(--ink-3)}
.treeside .legs{margin-bottom:var(--s4)}
.treeside .list .li{padding:var(--s2) 0}
.treeside .list .li .k{font-size:var(--fs-xs);color:var(--ink-3)}
.treeside .list .li .v{font-size:var(--fs-xs);text-align:right}
/* 닫기 단추는 좁은 화면에서만 쓴다 — 넓은 화면에서는 초기화가 그 일을 한다 */
.treeside .sideclose{display:none}

@media (max-width:820px){
  .treepane{display:block}
  /* ⚠️ 하단 탭바(fixed) 위로 올라와야 한다. 탭바 높이를 숫자로 적지 말고
     자리를 비워 두는 여백으로 민다 — 탭바는 앱마다 있고 없다. */
  .treeside{position:fixed;left:0;right:0;bottom:0;z-index:60;
    flex:none;max-height:52dvh;border-radius:var(--r-lg) var(--r-lg) 0 0;
    background:var(--surface);border-top:1px solid var(--hair);box-shadow:var(--glow);
    padding:var(--s5) var(--s4) calc(var(--s12) + env(safe-area-inset-bottom,0px));
    animation:sheetUp var(--t-base) var(--e-out) backwards}
  .treeside .sideclose{display:flex;position:absolute;right:var(--s4);top:var(--s4)}
}
/* ⚠️ 채우기는 `backwards` 다. `both` 면 끝난 뒤에도 항등 transform 이 남아
   그 안의 절대 위치 요소가 갇힌다 — 이 저장소에서 다섯 곳을 그렇게 고쳤다. */
@keyframes sheetUp{from{transform:translateY(100%)}}
@media (prefers-reduced-motion:reduce){.treeside{animation:none}}

/* 누를 수 있는 상자 */
.tbox.pick{cursor:pointer}
.tbox.pick:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.tbox.on{box-shadow:0 0 0 2px var(--brand)}
.tbox.root.on{box-shadow:0 0 0 2px var(--ink)}

.treewrap{position:relative}
/* ⚠️ `touch-action` 을 지우지 마라. 없으면 두 손가락 제스처를 브라우저가
   페이지 확대로 먼저 먹어서 트리는 그대로다. 한 손가락 스크롤은 남겨 둔다. */
.treebox[data-zoom]{touch-action:pan-x pan-y}
/* 배율만큼 커지는 상자 — 스크롤 범위를 이게 들고 있다.
   ⚠️ `display:block` 을 반드시 다시 준다. 위쪽 `.treebox > div{display:flex}` 가
      이 상자까지 잡아서, 안의 트리가 **flex 아이템이 되어 쭈그러든다.** 그러면
      쭈그러든 폭을 다시 재서 상자를 그만큼 줄이고, 그게 또 트리를 더 쭈그러뜨려
      누를 때마다 트리가 작아지는 되먹임이 생긴다. */
.treebox[data-zoom] > .treepan{position:relative;display:block;
  width:auto;min-width:0;margin-inline:auto}
.treebox[data-zoom] > .treepan > div{width:max-content;min-width:0;display:block;flex:none}

/* ⚠️ 오른쪽 **아래**에 두지 마라. 모바일에서 떠 있는 하단 탭바가 그 자리를
   지나가서 단추가 가려진다. 위쪽은 아무것도 지나가지 않는다.
   대신 트리 상자에 윗여백을 줘서 루트 노드와 겹치지 않게 한다. */
.treebox[data-zoom]{padding-top:var(--s10)}
/* 옆으로 더 있다 — 표(`.tw.over`)와 같은 말(가장자리 흐림)로 알린다.
   ⚠️ `.treebox` 안에 그리지 마라. 그 상자가 스크롤되는 당사자라 흐림이
      내용과 같이 흘러가 버린다. 스크롤되지 않는 `.treewrap` 에 얹는다.
   ⚠️ z-index 는 배율 단추(.zoomctl, 2)보다 낮게. 단추를 덮으면 못 누른다. */
.treewrap.moreL::before,
.treewrap.moreR::after{content:'';position:absolute;top:0;bottom:0;z-index:1;
  width:var(--s10);pointer-events:none}
.treewrap.moreL::before{left:0;border-radius:var(--r-lg) 0 0 var(--r-lg);
  background:linear-gradient(270deg,transparent,var(--bg-2) 72%)}
.treewrap.moreR::after{right:0;border-radius:0 var(--r-lg) var(--r-lg) 0;
  background:linear-gradient(90deg,transparent,var(--bg-2) 72%)}
/* 끌어서 옮길 수 있다는 표시. 마우스만 쓰는 사람에게는 이게 유일한 단서다 */
.treebox[data-zoom]{cursor:grab}
.treebox[data-zoom].grabbing,
.treebox[data-zoom].grabbing *{cursor:grabbing}
/* 끄는 동안 글자가 잡혀 파랗게 칠해지면 끌기가 아니라 선택으로 보인다.
   ⚠️ 상자에만 걸면 모자란다 — 끌다 보면 마우스가 상자 밖으로 나가고,
      그때부터 바깥 글자가 칠해진다. 끄는 동안은 문서 전체를 잠근다. */
body.treegrab{user-select:none;-webkit-user-select:none;cursor:grabbing}
body.treegrab *{cursor:grabbing}
.zoomctl{position:absolute;right:var(--s2);top:var(--s2);z-index:2;
  display:flex;align-items:center;gap:var(--s0);padding:var(--s1);
  background:var(--surface);border:1px solid var(--hair);border-radius:var(--r-full);
  box-shadow:var(--glow);backdrop-filter:var(--blur);-webkit-backdrop-filter:var(--blur)}
.zoomctl button{min-width:30px;height:30px;padding:0 var(--s2);cursor:pointer;
  background:none;border:0;border-radius:var(--r-full);
  font-family:var(--font);font-size:var(--fs-base);font-weight:var(--fw-semi);
  color:var(--ink-2);line-height:1;
  transition:background var(--t-fast) var(--e-out),color var(--t-fast) var(--e-out),
             transform var(--t-fast) var(--e-spring)}
.zoomctl button:hover:not(:disabled){background:var(--surface-2);color:var(--ink)}
.zoomctl button:active:not(:disabled){transform:scale(.9)}
.zoomctl button:disabled{opacity:.35;cursor:default}
.zoomctl .pct{min-width:52px;font-size:var(--fs-xs);font-variant-numeric:tabular-nums;
  color:var(--ink-3)}
.zoomctl button:focus-visible{outline:2px solid var(--accent-2);outline-offset:1px}

@media (max-width:820px){
  /* 손가락으로 벌리면 되니까 단추는 작게 — 대신 트리 자리를 더 준다 */
  .zoomctl{right:var(--s2);top:var(--s2);padding:var(--s0)}
  .zoomctl button{min-width:28px;height:28px}
  .zoomctl .pct{min-width:44px}
}

/* 표시자가 '다 펴진 배치' 를 재는 한 프레임 동안만 전환을 끈다.
   ⚠️ 이 규칙을 지우면 재는 동작 자체가 애니메이션이 되어 눈에 보인다. */
.tabbar.measuring *,.subnav.measuring *,.side nav.measuring *{
  transition:none !important;animation:none !important}

/* ═══════════════════════════════════════════════════════════
   탭 하이라이트 — 손가락으로 누른 자리에 브라우저가 칠하는 네모
   ⚠️ 이게 "활성 노란색이 옮겨갈 때 직사각형이 번쩍" 의 정체다.
      모바일 브라우저는 누른 요소 위에 반투명 사각형을 잠깐 칠하는데,
      **`border-radius` 를 따르지 않아** 알약 버튼 위에 각진 네모가 뜬다.
      마우스 클릭에서는 안 그려져서 PC 에서는 보이지 않는다 — 실기기에서만
      나오는 증상이라 놓치기 쉽다.
   ⚠️ 이 줄을 지우면 하단바·서브탭·칩을 누를 때마다 다시 번쩍인다.
   ═══════════════════════════════════════════════════════════ */
button,a,label.chk,[role="button"],summary{
  -webkit-tap-highlight-color:transparent;
}

/* 누르면서 손가락이 살짝 밀리면 글자가 선택돼 파란 네모가 남는다.
   ⚠️ 본문·금액·회원코드까지 막지 마라 — 복사해야 하는 값들이다.
      누르는 것이 일인 조작부에만 건다. */
.tabbar button,.subnav button,.side nav button,.seg button,.chip,
.zoomctl button,.quick button,.slot,.menubtn,.bellbtn,.prefsbtn,.logout,.btn{
  -webkit-user-select:none;user-select:none;
}

/* ── 통행 차단 안내 ───────────────────────────────────────────
   "지금 아무것도 안 되는 이유" 를 화면 맨 위에서 한 번에 말해 준다.
   ⚠️ 이걸 작은 글씨로 만들지 마라. 이 줄을 못 보면 사용자는 기능이 고장난
      줄 알고 개발자에게 전화한다 — 실제로 그렇게 됐다. */
.gatebox{display:flex;align-items:center;gap:var(--s4);flex-wrap:wrap;
  margin-bottom:var(--s6);padding:var(--s4) var(--s5);border-radius:var(--r-lg);
  background:var(--warn-bg);border:1px solid var(--warn);color:var(--ink)}
.gatebox b{display:block;font-size:var(--fs-base);font-weight:var(--fw-bold);color:var(--warn)}
.gatebox span{display:block;margin-top:var(--s1);font-size:var(--fs-sm);color:var(--ink-2)}
.gatebox > div{flex:1 1 220px;min-width:0}
.gatebox .btn{flex:0 0 auto}

/* 표 안의 회원코드 — 눌러서 그 회원 상세로 간다.
   ⚠️ 코드가 눌린다는 걸 보이게 해야 한다. 그냥 `<code>` 로 두면 아무도
      누를 생각을 못 해서, 만들어 둔 화면을 못 찾는다. */
.codebtn{background:none;border:0;padding:0;cursor:pointer;font:inherit;color:inherit}
.codebtn code{color:var(--accent);border-bottom:1px dashed currentColor;
  transition:color var(--t-fast) var(--e-out),background var(--t-fast) var(--e-out)}
.codebtn:hover code{color:var(--accent-2);background:var(--brand-bg)}
.codebtn:focus-visible{outline:2px solid var(--accent-2);outline-offset:2px;border-radius:var(--r-sm)}

/* ── 눌러서 복사되는 코드 ─────────────────────────────────────
   ⚠️ 코드를 그냥 글자로만 두지 마라. 회원은 이게 남에게 주는 코드인 줄 모르고,
      폰에서 길게 눌러 선택하는 것도 잘 안 된다. 누르면 복사되게 한다. */
.copy{display:inline-flex;align-items:center;gap:var(--s2);cursor:pointer;
  padding:var(--s1) var(--s2) var(--s1) var(--s3);
  background:var(--surface-2);border:1px solid var(--hair);border-radius:var(--r-full);
  font-family:var(--font);
  transition:background var(--t-fast) var(--e-out),border-color var(--t-fast) var(--e-out),
             transform var(--t-fast) var(--e-spring)}
.copy code{font-family:var(--mono);font-size:var(--fs-base);font-weight:var(--fw-bold);
  color:var(--ink);letter-spacing:var(--ls-num)}
.copy .lb{font-size:var(--fs-2xs);font-weight:var(--fw-semi);color:var(--ink-3);
  padding:var(--s1) var(--s2);border-radius:var(--r-full);background:var(--bg);
  white-space:nowrap}
.copy:hover{border-color:var(--accent)}
.copy:active{transform:scale(.97)}
.copy:focus-visible{outline:2px solid var(--accent-2);outline-offset:2px}
.copy.done{border-color:var(--ok)}
.copy.done .lb{background:var(--ok);color:#fff}
.copy.fail{border-color:var(--bad)}
.copy.fail .lb{background:var(--bad);color:#fff}
/* 값 칸에 들어가는 경우 — 오른쪽 정렬을 깨지 않는다 */
/* ⚠️ 값 칸 안에서는 알약 테두리를 지운다. 다른 줄의 값은 전부 칸 왼쪽 끝에
   딱 붙는데, 테두리 있는 알약은 제 안쪽 여백만큼 글씨를 밀어서 값 열이
   그 줄만 13px 어긋난다. 실제로 그 어긋남이 가장 먼저 눈에 띄었다.
   음수 마진으로 높이를 맞추려 들지도 마라 — 위 이름표를 파고든다. */
.kv .v .copy{margin:0;padding:0;background:none;border:0;border-radius:0;gap:var(--s3)}
/* 전역 `code` 가 제 배경·여백을 갖고 있다. 값 칸에서는 그것도 지워야
   글자가 다른 줄 값과 같은 자리에서 시작한다. 복사가 된다는 건
   옆의 `복사` 배지가 알린다. */
.kv .v .copy code{font-size:var(--fs-md);font-weight:var(--fw-semi);
  background:none;padding:0;border-radius:0}
.kv .v .copy .lb{border:1px solid var(--hair);background:var(--surface-2);color:var(--ink-3)}
.kv .v .copy.done .lb{border-color:transparent}
.kv .v .copy.fail .lb{border-color:transparent}
#homeInfoNote{margin:var(--s3) 0 0}
#homeRef{margin-top:var(--s5)}

/* 내 추천 링크 — 위 현황 카드(.trio·.prog)와 같은 결의 카드 한 장이다. */
.refcard{background:var(--bg-2);border-radius:var(--r-lg);padding:var(--s4)}
.refcard > .k{display:block;font-size:var(--fs-xs);color:var(--ink-3);
  margin-bottom:var(--s2)}
/*
 * 링크는 왼쪽, `복사` 는 오른쪽 끝, 둘의 **가운데를 맞춘다**.
 * ⚠️ `align-items:flex-start` 로 두지 마라. 링크가 두 줄이 되는 순간
 *    `복사` 배지만 첫 줄에 매달려 눈에 띄게 어긋난다 — 그렇게 어긋나 있었다.
 * ⚠️ 줄 전체가 하나의 단추다. 배지만 누르게 만들지 마라 — 좁은 화면에서
 *    손가락으로 겨냥할 폭이 안 나온다.
 */
.refcard .copy{display:flex;width:100%;align-items:center;
  justify-content:space-between;gap:var(--s3);
  /* ⚠️ 한 줄짜리 링크는 글자 높이(23px)밖에 안 돼서 손가락으로 겨냥하기
     어렵다. 줄 전체가 단추이므로 최소 높이를 준다 — 간격 검사가 잡았다. */
  min-height:var(--s8);
  margin:0;padding:0;background:none;border:0;border-radius:0}
/* 링크는 회원코드보다 훨씬 길다. 한 줄로 두면 좁은 화면에서 칸을 뚫으므로
   아무 데서나 접는다 — 잘리는 것보다 두 줄이 낫다. */
.refcard .copy code{flex:1;min-width:0;text-align:left;
  white-space:normal;overflow-wrap:anywhere;
  font-size:var(--fs-md);font-weight:var(--fw-semi);
  background:none;padding:0;border-radius:0}
.refcard .copy .lb{flex:none;border:1px solid var(--hair);
  background:var(--surface-2);color:var(--ink-3)}
.refcard .copy.done .lb{border-color:transparent}
.refcard .copy.fail .lb{border-color:transparent}
#homeRefHint{margin:var(--s3) 0 0}

/* ===========================================================
   손가락 크기 — 모바일에서만
   =========================================================== */
@media (max-width:820px){
  /* ⚠️ 마우스로 누를 때 알맞은 크기와 손가락으로 누를 때 알맞은 크기는 다르다.
     데스크톱에서 촘촘해 보이던 작은 단추들이 폰에서는 22~24px 밖에 안 돼서
     정확히 못 눌렀다. 폭은 그대로 두고 높이만 세운다. */
  .btn.sm,.slot,label.chk,.logout,button.link{min-height:32px}
  .btn.sm,.slot,.logout,button.link{display:inline-flex;align-items:center;
    justify-content:center}

  /* ⚠️ 줄 높이를 건드리면 안 되는 자리(값 칸·표 칸)에서는 높이를 키우는 대신
     누를 수 있는 넓이만 밖으로 늘린다. 눈에 보이는 건 그대로다. */
  .kv .v .copy,.codebtn{position:relative}
  .kv .v .copy::after,.codebtn::after{content:'';position:absolute;
    left:0;right:0;top:-7px;bottom:-7px}

  /* 조직도 확대·축소는 겹쳐 놓은 조작기라 키워도 배치가 안 흔들린다 */
  .zoomctl button{height:34px;min-width:34px}

  /* ⚠️ 좁아지면 막대 안 이름표가 반쯤 잘려 "센" 처럼 보인다. 잘린 글자는
     없는 것만 못하다 — 아래 범례(.barlegend)가 뜻을 대신 지고 있으니
     좁을 때는 아예 지운다. */
  .bar > div{font-size:0}
}

/* ===========================================================
   상담 단추 (우하단 고정)
   =========================================================== */
.support{
  position:fixed;right:var(--s5);z-index:60;
  bottom:calc(var(--s5) + env(safe-area-inset-bottom,0px));
  display:inline-flex;align-items:center;gap:var(--s2);
  padding:var(--s3) var(--s4);border:0;border-radius:var(--r-full);
  background:#FEE500;color:#191600;cursor:pointer;
  font-family:var(--font);font-size:var(--fs-sm);font-weight:var(--fw-semi);
  box-shadow:0 8px 24px rgba(0,0,0,.18);
  transition:transform var(--t-fast) var(--e-out),box-shadow var(--t-fast) var(--e-out);
}
.support:hover{transform:translateY(-2px);box-shadow:0 12px 28px rgba(0,0,0,.22)}
.support:active{transform:scale(.96)}
.support svg{width:20px;height:20px;fill:currentColor;flex:none}

/* ⚠️ 모바일에서는 하단 탭바 위로 올린다. 안 올리면 탭바에 깔려서
   마지막 탭을 누를 때마다 이 단추가 먼저 눌린다. */
@media (max-width:820px){
  .support{
    right:var(--s4);
    /* ⚠️ 하단바 높이만 빼면 딱 붙는다. 숨 쉴 자리를 더 준다. */
    bottom:calc(var(--tabbar-h) + var(--s6) + env(safe-area-inset-bottom,0px));
    padding:var(--s3);
  }
  .support span{display:none}          /* 좁은 곳에서는 말풍선만 */
  .shell.drawer .support{bottom:calc(var(--s4) + env(safe-area-inset-bottom,0px))}
}

/* 누른 뒤 한 줄 안내 — 붙여넣으라는 말을 여기서 한다 */
.supporttip{
  position:fixed;right:var(--s5);z-index:61;
  bottom:calc(var(--s5) + 56px + env(safe-area-inset-bottom,0px));
  max-width:min(280px,calc(100vw - var(--s8)));
  padding:var(--s3) var(--s4);border-radius:var(--r-md);
  background:var(--ink);color:var(--bg);
  font-size:var(--fs-sm);line-height:var(--lh-snug);
  box-shadow:var(--sh-2);
  opacity:0;transform:translateY(6px);pointer-events:none;
  transition:opacity var(--t-base) var(--e-out),transform var(--t-base) var(--e-out);
}
.supporttip.on{opacity:1;transform:none}
@media (max-width:820px){
  .supporttip{right:var(--s4);
    bottom:calc(var(--tabbar-h) + var(--s6) + 52px + env(safe-area-inset-bottom,0px))}
  .shell.drawer .supporttip{bottom:calc(var(--s4) + 52px + env(safe-area-inset-bottom,0px))}
}

/* 로그인 카드 아래 입구 (회원가입 · 찾기) */
.authlinks{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:var(--s2);margin-top:var(--s5);font-size:var(--fs-sm);color:var(--card-ink-2,#9aa4b8)}
.authlinks button.link{color:inherit;text-decoration:none;border-bottom:1px solid transparent}
.authlinks button.link:hover{color:var(--accent-2);border-bottom-color:currentColor}
/* ⚠️ 카드 안에서는 링크 줄이 한 장에 하나만 보여야 한다. 안 그러면 '가입'
   장에서도 '가입' 링크가 또 뜬다. 장 안의 것은 장이 정한다. */
#authView .authlinks{margin-top:var(--s6)}
.authpane.hide{display:none}

/* 고르는 칸 — 가입할 때 "들어갈 자리".
   ⚠️ `.login .ctl input` 규칙을 그대로 물려받지 못한다(선택자가 input 이다).
      같은 모양으로 따로 적어 준다 — 안 적으면 이 칸만 브라우저 기본
      모양으로 떠서 폼 한가운데가 튄다. */
.login .ctl select{width:100%;margin:0;padding:var(--s3) var(--s4);
  border-radius:10px;font-size:var(--fs-md);color:var(--card-ink);
  background:var(--ground);border:1px solid var(--hair);
  min-height:44px;cursor:pointer;
  transition:border-color var(--t-base) var(--e-out),box-shadow var(--t-base) var(--e-out)}
.login .ctl select:focus{outline:none;border-color:var(--accent-2);
  box-shadow:0 0 0 3px rgba(232,163,61,.18)}
.login .ctl select:disabled{cursor:default;opacity:.6}

/* 잠긴 입력칸 — 추천 링크로 채워진 추천인 코드.
   ⚠️ 회색으로 죽여 두지 마라. "고장났다" 로 읽힌다. 글자는 또렷하게 두고
      자물쇠로 "일부러 잠갔다" 를 말한다. */
.login .ctl input.locked{cursor:default;padding-right:38px}
/* ⚠️ `.ctl` 은 flex 가 아니라 position:relative 다. `.eye` 와 똑같이
      절대 위치로 오른쪽에 붙여야 칸 안에 들어간다. */
.login .ctl .lockic{position:absolute;right:var(--s3);top:50%;transform:translateY(-50%);
  width:17px;height:17px;pointer-events:none;
  fill:none;stroke:var(--card-ink-3);stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round}
.login .ctl .lockic.hide{display:none}

/* 입력칸 바로 아래 한 줄 — 아이디 중복 확인 같은 즉시 안내 */
.fldnote{margin:calc(var(--s2) * -1) 0 var(--s4);font-size:var(--fs-xs);
  line-height:var(--lh-snug);color:var(--card-ink-2,#9aa4b8)}
.fldnote:empty{margin:0}
.fldnote.ok{color:var(--ok)}
.fldnote.no{color:var(--bad)}
.fldnote.mut{opacity:.7}

/* 공개 주소로 들어온 첫 순간 — 로그인 카드를 그리지 않는다 (index.html 머리말).
   ⚠️ 화면 코드가 `#loginView` 에 `hide` 를 붙이는 즉시 이 클래스를 떼야 한다.
      안 떼면 "로그인 화면으로" 를 눌러도 카드가 영영 안 나온다. */
html.authboot #loginView{display:none}

/* 로그인한 채로 공개 주소를 열었을 때 카드 맨 위에 붙는 한 줄 */
.authwho{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2);
  margin-bottom:var(--s5);padding:var(--s3) var(--s4);border-radius:var(--r-sm);
  background:rgba(255,255,255,.06);font-size:var(--fs-sm);
  color:var(--card-ink-2,#9aa4b8);line-height:var(--lh-snug)}
.authwho.hide{display:none}
.authwho button.link{color:var(--accent-2);border-bottom:1px solid transparent}
.authwho button.link:hover{border-bottom-color:currentColor}
#authView .authpane .hint{margin-top:var(--s5)}

/* 가입 신청 줄 — 누를 수 있는 것만 누를 수 있게 보인다 */
.rows .r.pick{cursor:pointer}
.rows .r.pick:hover{background:var(--surface-2)}
/* ⚠️ 이메일은 끊을 자리가 없는 한 덩어리다. 그냥 두면 360px 폭에서 줄 밖으로
   삐져나간다. 말줄임으로 감추지 마라 — 누구 신청인지 가리는 유일한 단서가
   메일 주소라 `admslot17…` 로 잘리면 쓸모가 없다. 아무 데서나 접는다. */
.rows .r .sub{display:block;font-size:var(--fs-xs);color:var(--ink-3);margin-top:var(--s0);
  overflow-wrap:anywhere}
/* ⚠️ 처리할 것이 있다는 표시. 숫자를 적지 마라 — 자리도 좁고, 숫자가
   맞는지 신경 쓰게 만든다. 있다/없다만 알면 눌러서 확인한다. */
.subnav .dot{display:inline-block;width:6px;height:6px;margin-left:var(--s1);
  border-radius:var(--r-full);background:var(--bad);vertical-align:middle}
.subnav button.on .dot{background:var(--on-accent)}
#rqPick,#rqDone{margin-top:var(--s5)}
#rqDone .kv{margin-bottom:var(--s4)}

/* ═══════════════════════════════════════════════════════════
   표면 v3 — 리디자인 시안(2026-10) 반영

   종이에 가까운 크림 바탕(데이) · 먹색 글씨 · 금색 하나.
   글꼴은 IBM Plex Sans KR, 숫자는 IBM Plex Mono.
   위 v2 와 같은 자리를 **토큰과 면만** 다시 칠한다 — 컴포넌트 규칙은
   손대지 않는다. 시안: claude.ai/artifact/QbZRgmsJPVEpJmtmimXKWB

   ⚠️ 나이트는 [data-theme="dark"] 와 system+OS다크 두 곳에 같은 값을 적는다.
      한쪽만 고치면 설정에 따라 다른 앱이 된다.
   ═══════════════════════════════════════════════════════════ */
:root,:root[data-theme="light"]{
  --font:"IBM Plex Sans KR",-apple-system,BlinkMacSystemFont,"Apple SD Gothic Neo",
         "Malgun Gothic",system-ui,sans-serif;
  --mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace;

  /* 먹 */
  --ink:#15171A; --ink-2:#4B5059; --ink-3:#767B86;
  /* 바탕 — 크림 */
  --ground:#F7F5F1;            /* 앱 바닥 */
  --bg:#FFFFFF;                /* 판 */
  --bg-2:#F1EEE8;              /* 블록 바탕 */
  --bg-3:#E6E2D9;              /* 눌린 면·트랙 */
  --line:#E4E0D7;
  --surface:#FFFFFF; --surface-2:#F1EEE8;
  --hair:#E4E0D7;
  --pill:#EFECE5;              /* 내비 알약 — 금색이 아니라 베이지 */
  --seg-sel:#FFFFFF;           /* 세그먼트·서브탭의 고른 칸 — 어둠에서는 바탕보다 밝아야 한다 */
  /* 금색 — 글씨용과 면용을 가른다 */
  --accent:#8A5F04;            /* 흰 바탕 위 글씨 */
  --accent-2:#E0A008;          /* 밝은 쪽 */
  --on-accent:#1F1503;
  --on-accent-2:rgba(31,21,3,.78); --on-accent-3:rgba(31,21,3,.68);
  --on-accent-bg:rgba(31,21,3,.12);
  --brand-bg:#F9EFD6;
  --fill-1:#E8AE1C; --fill-2:#E0A008; --fill:#E0A008;   /* 면은 단색 */
  /* 의미색 */
  --up:#C3342A; --ok:#0C7B55; --ok-bg:#DFF2EA;
  --warn:#8A5F04; --warn-bg:#F9EFD6;
  --bad:#C3342A; --bad-bg:#FAE7E4;
  /* 그림자 — 닿는 1px + 퍼지는 겹 */
  --sh-1:0 1px 2px rgb(30 26 18/.06);
  --glow:0 1px 2px rgb(30 26 18/.05);
  --card-sh:0 1px 2px rgb(30 26 18/.06),0 20px 50px rgb(30 26 18/.13);
  --r-lg:20px;
  --tree-line:#A9A092;
  --line-2:#D2CCC0; --sunken:#FAF9F6; --info:#1B6790; --info-bg:#E2EEF5;
  --sh-2:0 1px 2px rgb(30 26 18/.06),0 8px 24px rgb(30 26 18/.07);
  --sh-3:0 1px 2px rgb(30 26 18/.07),0 24px 60px rgb(30 26 18/.14);
  --sh-dock:0 1px 2px rgb(30 26 18/.06),0 10px 28px rgb(30 26 18/.11);
}
:root[data-theme="dark"]{
  --ink:#ECEEF2; --ink-2:#99A2B1; --ink-3:#79808D;
  --ground:#0D0F13; --bg:#15181F; --bg-2:#1C212A; --bg-3:#242A33; --line:#1F242C;
  --surface:#15181F; --surface-2:#1C212A; --hair:#1F242C; --pill:#232936; --seg-sel:#2B3240;
  --accent:#F0B93C; --accent-2:#F0B93C; --on-accent:#120F08;
  --on-accent-2:rgba(18,15,8,.78); --on-accent-3:rgba(18,15,8,.68); --on-accent-bg:rgba(18,15,8,.14);
  --brand-bg:#2A2314;
  --fill-1:#F4C455; --fill-2:#F0B93C; --fill:#F0B93C;
  --up:#F0564A; --ok:#3FD69B; --ok-bg:#10261F; --warn:#F0B93C; --warn-bg:#2A2314; --bad:#F0564A; --bad-bg:#2A1715;
  --sh-1:0 1px 2px rgb(0 0 0/.5); --glow:0 1px 2px rgb(0 0 0/.5);
  --card-sh:0 1px 2px rgb(0 0 0/.5),0 24px 60px rgb(0 0 0/.6);
  --tree-line:#3E4654;
    --line-2:#2B313B; --sunken:#111419; --info:#7FD8FF; --info-bg:#13242D;
    --sh-2:0 1px 2px rgb(0 0 0/.5),0 8px 24px rgb(0 0 0/.45);
    --sh-3:0 1px 2px rgb(0 0 0/.5),0 24px 60px rgb(0 0 0/.6);
    --sh-dock:0 1px 2px rgb(0 0 0/.5),0 10px 30px rgb(0 0 0/.55);
}
@media (prefers-color-scheme:dark){
  :root[data-theme="system"]{
    --ink:#ECEEF2; --ink-2:#99A2B1; --ink-3:#79808D;
    --ground:#0D0F13; --bg:#15181F; --bg-2:#1C212A; --bg-3:#242A33; --line:#1F242C;
    --surface:#15181F; --surface-2:#1C212A; --hair:#1F242C; --pill:#232936; --seg-sel:#2B3240;
    --accent:#F0B93C; --accent-2:#F0B93C; --on-accent:#120F08;
    --on-accent-2:rgba(18,15,8,.78); --on-accent-3:rgba(18,15,8,.68); --on-accent-bg:rgba(18,15,8,.14);
    --brand-bg:#2A2314;
    --fill-1:#F4C455; --fill-2:#F0B93C; --fill:#F0B93C;
    --up:#F0564A; --ok:#3FD69B; --ok-bg:#10261F; --warn:#F0B93C; --warn-bg:#2A2314; --bad:#F0564A; --bad-bg:#2A1715;
    --sh-1:0 1px 2px rgb(0 0 0/.5); --glow:0 1px 2px rgb(0 0 0/.5);
    --card-sh:0 1px 2px rgb(0 0 0/.5),0 24px 60px rgb(0 0 0/.6);
    --tree-line:#3E4654;
    --line-2:#2B313B; --sunken:#111419; --info:#7FD8FF; --info-bg:#13242D;
    --sh-2:0 1px 2px rgb(0 0 0/.5),0 8px 24px rgb(0 0 0/.45);
    --sh-3:0 1px 2px rgb(0 0 0/.5),0 24px 60px rgb(0 0 0/.6);
    --sh-dock:0 1px 2px rgb(0 0 0/.5),0 10px 30px rgb(0 0 0/.55);
  }
}
@media (prefers-color-scheme:light){
  :root[data-theme="system"]{
    --ink:#15171A; --ink-2:#4B5059; --ink-3:#767B86;
    --ground:#F7F5F1; --bg:#FFFFFF; --bg-2:#F1EEE8; --bg-3:#E6E2D9; --line:#E4E0D7;
    --surface:#FFFFFF; --surface-2:#F1EEE8; --hair:#E4E0D7; --pill:#EFECE5; --seg-sel:#FFFFFF;
    --accent:#8A5F04; --accent-2:#E0A008; --on-accent:#1F1503;
    --brand-bg:#F9EFD6; --fill-1:#E8AE1C; --fill-2:#E0A008; --fill:#E0A008;
    --up:#C3342A; --ok:#0C7B55; --ok-bg:#DFF2EA; --warn:#8A5F04; --warn-bg:#F9EFD6; --bad:#C3342A; --bad-bg:#FAE7E4;
    --sh-1:0 1px 2px rgb(30 26 18/.06); --glow:0 1px 2px rgb(30 26 18/.05);
    --card-sh:0 1px 2px rgb(30 26 18/.06),0 20px 50px rgb(30 26 18/.13);
    --tree-line:#A9A092;
    --line-2:#D2CCC0; --sunken:#FAF9F6; --info:#1B6790; --info-bg:#E2EEF5;
    --sh-2:0 1px 2px rgb(30 26 18/.06),0 8px 24px rgb(30 26 18/.07);
    --sh-3:0 1px 2px rgb(30 26 18/.07),0 24px 60px rgb(30 26 18/.14);
    --sh-dock:0 1px 2px rgb(30 26 18/.06),0 10px 28px rgb(30 26 18/.11);
  }
}
/* 금색 글씨는 --accent, 금색 면은 --fill. 위에서 --brand 를 --accent 로 묶어 둔 것은 그대로 */
:root,:root[data-theme="dark"],:root[data-theme="system"],:root[data-theme="light"]{
  --brand:var(--accent); --brand-ink:var(--accent);
}

/* ── 숫자는 모노 ─────────────────────────────────────────── */
.n,.big,.v,td.n,th.n,.stat .v,.amount .big,.kv b,.lr,.tbox .c,.tbox .n,.copy,.tagpill.mono{
  font-family:var(--mono);font-weight:var(--fw-medium);letter-spacing:var(--ls-num)}
.amount .big{font-weight:var(--fw-medium);color:var(--accent);letter-spacing:var(--ls-display)}
h1,h2,.hd h1{letter-spacing:var(--ls-title)}

/* ── 판 — 흰 종이, 가는 테두리, 둥근 20 ──────────────────── */
.card,.list,.prog,.trio,.stats,.tblwrap,.empty,.warnbox{
  background:var(--surface);border:1px solid var(--hair);border-radius:var(--r-lg);box-shadow:var(--glow)}
.seg,.subnav{background:var(--surface-2);border:1px solid var(--hair)}
/* 세그먼트 — 바깥 12 · 안쪽 8 로 동심이어야 한다. 바깥 8 에 안쪽 6 이면 고른 칸의
   모서리가 바깥 테두리와 따로 논다(실제로 그렇게 보였다). 고른 칸은 흰 면 +
   가는 테두리 한 겹 — 베이지 위 베이지로는 고른 게 안 보인다. */
.seg{border-radius:12px;padding:var(--s1);gap:var(--s0)}
.seg button{border-radius:8px}
.seg button.on,.seg button[aria-selected="true"]{background:var(--seg-sel);box-shadow:0 0 0 1px var(--hair),var(--sh-1);color:var(--ink)}
.stat{box-shadow:0 0 0 1px var(--hair)}
thead th{color:var(--ink-3);font-weight:var(--fw-medium)}
tbody tr:hover{background:var(--bg-2)}

/* ── 내비 알약은 베이지, 글씨는 먹색, 아이콘만 금색 ──────── */
.side nav .navind,.side nav button.on,.shell.drawer .side nav button.on,
.tabbar .tabind{background:var(--pill)}
/* 서브탭 표시자 — 알약색(--pill)은 서브탭 바탕(--surface-2)과 거의 같은 베이지라
   고른 장이 안 보였다. 세그먼트와 같은 흰 면 + 가는 테두리로 맞춘다. */
.subnav .subind{background:var(--seg-sel);box-shadow:0 0 0 1px var(--hair),var(--sh-1)}
.side nav button.on,.shell.drawer .side nav button.on,.tabbar button.on,.subnav button.on{color:var(--ink)}
.subnav button.on .dot{background:var(--bad)}
.side nav button.on::before{content:'';position:absolute;left:0;top:50%;width:3px;height:18px;margin-top:-9px;
  border-radius:0 3px 3px 0;background:var(--fill)}
.side nav button{position:relative}
@media (max-width:820px){
  .tabbar{left:var(--s3);right:var(--s3);bottom:calc(var(--s3) + env(safe-area-inset-bottom,0px));
    border-radius:21px;background:color-mix(in srgb,var(--surface) 93%,transparent);
    border:1px solid var(--hair);box-shadow:0 1px 2px rgb(30 26 18/.06),0 10px 28px rgb(30 26 18/.11);
    backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px)}
  .tabbar .tabind{border-radius:15px;box-shadow:none}
  .tabbar button.on{color:var(--ink)}
  .tabbar button.on svg{color:var(--accent)}
  /* 독 윗선의 금색 레일 — 고른 탭 위에 짧게 */
  .tabbar button.on::before{content:'';position:absolute;top:calc(-1 * var(--s2) - 1px);left:30%;right:30%;height:2px;
    border-radius:2px;background:var(--fill);opacity:.95}
  .tabbar button{overflow:visible}
}
:root[data-theme="dark"] .tabbar,:root[data-theme="system"] .tabbar{box-shadow:0 1px 2px rgb(0 0 0/.5),0 10px 30px rgb(0 0 0/.55)}

/* ── 단추 — 금색 단색 + 먹색 글씨 ────────────────────────── */
.btn.primary{background:var(--fill);color:var(--on-accent);
  box-shadow:0 1px 2px rgb(140 95 0/.22),0 6px 16px rgb(190 140 10/.2)}
.btn.primary:hover{background:var(--fill);filter:brightness(1.05);
  box-shadow:0 1px 2px rgb(140 95 0/.26),0 10px 26px rgb(190 140 10/.3)}
.btn{background:var(--surface-2);border:1px solid var(--hair);color:var(--ink)}
.btn:hover{background:var(--bg-3)}
.tagpill.b{background:var(--brand-bg);color:var(--accent)}
.tbox.root{background:var(--fill)}
.tbox{border-left-width:3px}
.prog .track i,.seesaw i span{background:var(--fill)}

/* ── 입력란 — 흰 판 위에서는 크림, 크림 위에서는 흰 ─────── */
input,select,textarea{background:var(--ground);border:1px solid var(--bg-3);color:var(--ink);border-radius:11px}
input:focus,select:focus,textarea:focus{border-color:var(--accent-2);box-shadow:0 0 0 3px var(--brand-bg)}

/* ── 상단 헤더·사이드 ──────────────────────────────────────── */
.topbar,.apphd,header.hd{background:var(--surface);border-bottom:1px solid var(--hair)}
.side{background:var(--surface);border-right:1px solid var(--hair)}
.brand .dot{background:var(--fill);color:var(--on-accent)}

/* ── 모션: 스프링을 시안 값으로 ─────────────────────────── */
:root{--e-spring:cubic-bezier(.3,1.25,.5,1)}

/* ── 스플래시 — 심볼·워드마크 영상 ───────────────────────── */
.splash{position:fixed;inset:0;z-index:1000;display:flex;align-items:center;justify-content:center;overflow:hidden;
  background:radial-gradient(ellipse 70% 55% at 50% 48%,#F3EFE7 0%,#EDE6DA 70%,#E7DECF 100%)}
.splash[hidden]{display:none}
.splash video{width:100%;height:100%;object-fit:cover;display:block}
@media (min-aspect-ratio:3/4){.splash video{width:auto;object-fit:contain}}
.splash .skip{position:absolute;right:var(--s5);bottom:calc(var(--s6) + env(safe-area-inset-bottom,0px));
  border:1px solid rgb(80 60 20/.18);background:rgb(255 255 255/.55);color:#6B5A3A;font:inherit;font-size:var(--fs-xs);
  font-weight:var(--fw-semi);padding:var(--s2) var(--s3);border-radius:var(--r-full);cursor:pointer;opacity:0;
  animation:splashfade 400ms var(--e-out) 900ms forwards}
@keyframes splashfade{to{opacity:1}}
.splash.out{animation:splashout 420ms cubic-bezier(.4,0,1,1) forwards}
@keyframes splashout{to{opacity:0;transform:scale(1.03)}}
.cssplash{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--s8)}
.cssplash[hidden]{display:none}
.cssplash .s1{width:120px;opacity:0;transform:scale(.7) translateY(10px);animation:splashpop 900ms var(--e-spring) 200ms forwards}
.cssplash .s2{height:34px;opacity:0;transform:translateY(12px);animation:splashrise 700ms var(--e-out) 1100ms forwards}
.cssplash .s3{width:120px;height:2px;background:rgb(140 95 0/.15);border-radius:2px;overflow:hidden;opacity:0;animation:splashfade 300ms 1500ms forwards}
.cssplash .s3 i{display:block;height:100%;background:var(--fill);transform:scaleX(0);transform-origin:left;animation:splashsweep 1300ms var(--e-out) 1500ms forwards}
@keyframes splashpop{to{opacity:1;transform:none}}
@keyframes splashrise{to{opacity:1;transform:none}}
@keyframes splashsweep{to{transform:scaleX(1)}}
/* 스플래시가 떠 있는 동안 뒤의 로그인 등장 모션은 잠깐 멈춘다 */
html.splashing .login{animation-play-state:paused}
@media (prefers-reduced-motion:reduce){.splash,.splash .skip,.cssplash *{animation:none;opacity:1;transform:none}}

/* 알림 발송 — 발송 내역 거르기 세그먼트는 좁은 화면에서 옆으로 흘린다(360px) */
.subpane[data-sub="log"] .row.wrap label:has(> .seg){flex:1 1 100%;min-width:0;flex-direction:column;align-items:flex-start;gap:var(--s2)}
#ntChannel,#ntStatus{display:flex;max-width:100%;overflow-x:auto;scrollbar-width:none}
#ntChannel::-webkit-scrollbar,#ntStatus::-webkit-scrollbar{display:none}
#ntChannel button,#ntStatus button{flex:0 0 auto}
/* 채널 점검 통계는 위 상자와 한 숨 띄운다 */
#ntStats .stats{margin-top:var(--s5);margin-bottom:var(--s5)}

/* ===========================================================
   표면 v3 — 인증 화면(로그인·가입·찾기·관리자 로그인)을 시안대로.
   노치·모서리 조각·유리면은 걷어낸다 — 시안은 평평한 흰 카드 하나다.
   id·구조는 그대로 두고(lib.js 가 .morph 로 전환을 건다) 겉만 바꾼다.
   =========================================================== */
.login{--card-ink:var(--ink);--card-ink-2:var(--ink-2);--card-ink-3:var(--ink-3);
  gap:72px;padding-block:28px;padding-inline:24px}
.login .box{max-width:400px;padding:28px 26px 24px;--notch:none}
.login .corner{display:none}
.login .pane{-webkit-mask:none;mask:none;filter:none;border-radius:24px;
  background:var(--surface);border:1px solid var(--line);box-shadow:var(--sh-2)}
.login .pane::after{display:none}
.login .prefsbtn.onlogin{top:26px;right:22px;color:var(--ink-3);z-index:3}

/* 왼쪽 히어로 — PC 에서만, 심볼 + 한 문장 */
.login .hero{display:none;width:300px;flex-direction:column;gap:22px;flex:none}
.login .hero .sym{width:150px;height:auto;display:block}
.login .hero .h{font-size:26px;font-weight:700;letter-spacing:-.04em;line-height:1.2;color:var(--ink)}
.login .hero p{font-size:13px;color:var(--ink-3);line-height:1.7;margin:12px 0 0}
@media (min-width:900px){.login .hero{display:flex}}

/* 머리 — 워드마크 왼쪽, 톱니 오른쪽 */
.login .loginlogo{height:30px;margin:0 0 22px;display:block}
.login h1{font-size:18px;font-weight:600;letter-spacing:-.025em;margin:0 0 18px;color:var(--ink)}
.login h1 em{color:inherit}
#loginView .sub,#adLoginView .sub{display:none}
.login .sub{font-size:12px;color:var(--ink-3);margin:-10px 0 18px}

/* 칸 — 라벨 11px, 입력 크림 바탕 */
.login .fld{margin:0 0 12px}
.login .fld > span{font-size:11px;font-weight:500;color:var(--ink-3);margin-bottom:7px;letter-spacing:0}
.login .ctl .ic{display:none}
.login .ctl input{padding:12px 13px;border-radius:11px;font-size:13px;
  background:var(--ground);border:1px solid var(--line-2);color:var(--ink)}
.login .ctl input:has(~ .eye){padding-right:40px}
.login .ctl input::placeholder{color:var(--ink-3)}
.login .ctl input:focus{border-color:var(--fill);box-shadow:0 0 0 3px var(--brand-bg)}
.login .ctl:focus-within .ic{stroke:var(--accent)}
.login .ctl .selbtn{background:var(--ground);border-color:var(--line-2);border-radius:11px;min-height:0;padding:12px 13px;font-size:13px}
.login .fldrow{margin:0 0 6px}
.login .chk{font-size:12px;color:var(--ink-2)}
.login .chk input{border-color:var(--line-2);background:var(--ground)}
.login .chk input:checked{background:var(--fill);border-color:var(--fill)}
.login .chk input:checked::after{border-color:var(--on-accent)}
.login .legbtn{border-radius:11px;border-color:var(--line-2)}
.login .legbtn.on{background:var(--fill);border-color:var(--fill);color:var(--on-accent);box-shadow:none}
.login .legbtn.on .why{color:var(--on-accent)}
.login .legbtn:not(:disabled):hover{border-color:var(--fill)}

/* 단추 — 금색 단색, 글자만 */
.login .btn{border-radius:15px;padding:15px;font-size:14px;font-weight:700;margin-top:18px}
.login .btn.primary,.login .btn.primary.cta{background:var(--fill);color:var(--on-accent);
  border-radius:15px;padding:15px;font-size:14px;letter-spacing:-.015em;position:relative;overflow:hidden;
  box-shadow:0 1px 2px rgb(140 95 0/.22),0 6px 16px rgb(190 140 10/.2)}
.login .btn.primary:hover,.login .btn.primary.cta:hover{filter:none;
  box-shadow:0 1px 2px rgb(140 95 0/.26),0 10px 26px rgb(190 140 10/.3)}
.login .btn.primary::after{content:'';position:absolute;top:0;bottom:0;width:38%;left:-45%;
  background:linear-gradient(100deg,transparent,rgb(255 255 255/.4),transparent);transform:skewX(-18deg);pointer-events:none}
.login .btn.primary:hover::after{animation:sheen 760ms var(--e-out)}
@keyframes sheen{to{left:125%}}
.login .btn.primary.cta svg{display:none}
.login .btn.ghost,.login .btn:not(.primary){background:var(--pill);color:var(--ink);box-shadow:none}

.login .authlinks,.authlinks{gap:14px;margin-top:16px;font-size:12px;color:var(--ink-3)}
.authlinks button.link{font-size:12px;color:var(--ink-3);padding:4px 2px;border-bottom:0}
.authlinks button.link:hover{color:var(--ink);border-bottom:0}
.login .hint{border-top-color:var(--line);color:var(--ink-3);font-size:11px}
.login .hint b{color:var(--ink-2)}
.login .msg{font-size:12px}
@media (max-width:420px){.login{padding:20px 16px}.login .box{padding:24px 20px 20px}}

/* ===========================================================
   표면 v3 — 어드민 콘솔을 시안대로 (사이드바 아이콘·⌘K·배지, KPI 카드,
   페이지 머리, 패널, 일별 지급액 차트, 손이 필요한 것, 지급률)
   =========================================================== */
/* 사이드바 */
.side{width:224px;--side-w:224px}
.side .brand strong{font-size:13px;font-weight:600;letter-spacing:-.02em}
.side .brand em{font-size:10px;letter-spacing:.06em;color:var(--ink-3)}
.side nav{gap:2px;padding:0 var(--s3)}
.side nav button{display:flex;align-items:center;gap:var(--s3);padding:var(--s2) var(--s3);border-radius:12px;
  font-size:13px;font-weight:500;color:var(--ink-3);letter-spacing:-.01em;
  transition:color var(--t-fast) var(--e-out),transform var(--t-fast) var(--e-out)}
.side nav button:hover{color:var(--ink);background:transparent;transform:translateX(2px)}
.side nav button.on{color:var(--ink);font-weight:600}
.side nav button > svg{width:17px;height:17px;flex:none;color:var(--ink-3);opacity:.8;transition:color var(--t-fast)}
.side nav button.on > svg{color:var(--accent);opacity:1}
.side nav button > span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.side nav .navind{border-radius:12px;background:var(--pill)}
.navbadge{font-family:var(--mono);font-style:normal;font-size:10.5px;font-weight:600;padding:var(--s0) var(--s2);border-radius:999px;
  background:var(--brand-bg);color:var(--accent);margin-left:auto}
.navbadge[hidden]{display:none}
.findbtn{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:var(--s3) var(--s3) 0;
  padding:8px 12px;border:1px solid var(--line);border-radius:10px;background:transparent;color:var(--ink-3);
  font-family:var(--font);font-size:11.5px;font-weight:600;cursor:pointer;
  transition:background var(--t-fast),color var(--t-fast),border-color var(--t-fast)}
.findbtn > span{display:flex;align-items:center;gap:var(--s2)}
.findbtn svg{width:13px;height:13px}
.findbtn:hover{background:var(--pill);color:var(--ink);border-color:var(--line-2)}
.kbd{font-family:var(--mono);font-size:10px;color:var(--ink-3);border:1px solid var(--line-2);border-radius:5px;padding:1px var(--s1)}
.sidefoot{font-size:11px;color:var(--ink-3);line-height:1.5;padding:var(--s3) var(--s5) 0;margin-top:var(--s3)}
@media (max-width:820px){
  .side{width:100%}
  .findbtn{display:none}
  .shell.drawer .side nav button{flex:1 1 44%;justify-content:center;background:var(--bg-2);color:var(--ink-2);transform:none}
  .shell.drawer .side nav button.on{background:var(--pill);color:var(--ink)}
  .shell.drawer .side nav button > span{flex:none}
  .side nav button.on::before{display:none}
}

/* 페이지 머리 */
.pagehd{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s4);flex-wrap:wrap}
.pagehd h1{margin:0;font-size:26px;letter-spacing:-.045em;line-height:1.15}
.pagesub{margin:var(--s1) 0 0;font-size:13px;color:var(--ink-3);line-height:1.5}
.pagesub:empty{display:none}
.pagehd-act{display:flex;align-items:center;gap:var(--s2)}
.livepill{display:inline-flex;align-items:center;gap:var(--s2);font-size:12px;color:var(--ink-2);background:var(--surface);
  border:1px solid var(--line);padding:var(--s2) var(--s3);border-radius:11px}
.livepill i{width:6px;height:6px;border-radius:999px;background:var(--ok);display:inline-block;animation:livepulse 2.4s ease-in-out infinite}
@keyframes livepulse{0%,100%{opacity:1}50%{opacity:.35}}
.btn.sm{font-size:13px;padding:var(--s3) var(--s4);border-radius:12px}

/* KPI 카드 — 선으로 이어 붙인 격자가 아니라 떨어진 카드 */
.stats{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:var(--s3);background:transparent;border:0;box-shadow:none;padding:0;border-radius:0}
.stat{background:var(--surface);border:1px solid var(--line);border-radius:17px;padding:var(--s4) var(--s5);min-width:0;box-shadow:none;
  transition:transform var(--t-base) var(--e-out),box-shadow var(--t-base) var(--e-out)}
@media (hover:hover){.stat:hover{transform:translateY(-2px);box-shadow:var(--sh-1)}}
.stat .k{font-size:11px;color:var(--ink-3);margin-bottom:0;white-space:normal}
.stat .v{display:block;font-family:var(--mono);font-size:24px;font-weight:500;letter-spacing:-.04em;margin-top:8px;
  font-variant-numeric:tabular-nums;line-height:1.1}
.stat .u{display:block;font-size:11px;color:var(--ink-3);margin:var(--s2) 0 0;font-weight:500;font-family:var(--font);letter-spacing:0;line-height:1.5}
.stat .u:empty{display:none}
.stat.gold{background:var(--brand-bg);border-color:#E8D5A0}
:root[data-theme="dark"] .stat.gold{border-color:#4A3C1C}
@media (max-width:600px){.stats{grid-template-columns:1fr 1fr}.stat .v{font-size:20px;overflow:hidden;text-overflow:ellipsis}}

/* 두 칸 격자 · 패널 */
.g2{display:grid;grid-template-columns:1.55fr 1fr;gap:var(--s4);align-items:start}
@media (max-width:900px){.g2{grid-template-columns:1fr}}
.card.panel{padding:var(--s5);border-radius:19px}
.panelhd{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--s3);flex-wrap:wrap}
.sect{font-size:13.5px;font-weight:600;letter-spacing:-.015em;color:var(--ink)}
.sect small{font-size:10.5px;color:var(--ink-3);font-weight:500}
.sectsub{font-size:11px;color:var(--ink-3);margin-top:4px}
.legend{display:flex;gap:var(--s4);font-size:11px;color:var(--ink-2)}
.legend > span{display:flex;align-items:center;gap:var(--s2)}
.legend .sq{width:9px;height:9px;border-radius:3px;background:var(--fill);display:inline-block}
.legend .ln{width:9px;height:2px;background:var(--info);display:inline-block}

/* 일별 지급액 */
.dchart{position:relative;margin-top:var(--s4);min-height:60px}
.dbars{display:flex;align-items:flex-end;gap:8px;height:194px}
.dcol{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:8px;height:100%}
.dbar{width:100%;border-radius:5px 5px 2px 2px;background:var(--bg-3);transform-origin:bottom;animation:barup .7s var(--e-out) backwards}
.dbar.last{background:var(--fill)}
@keyframes barup{from{transform:scaleY(0)}}
.dcol .n{font-size:9px;color:var(--ink-3);font-family:var(--mono)}
.dline{position:absolute;left:0;top:0;width:100%;height:172px;pointer-events:none;overflow:visible}
.dline polyline{fill:none;stroke:var(--info);stroke-width:2;stroke-linejoin:round;stroke-linecap:round;
  stroke-dasharray:1200;stroke-dashoffset:1200;animation:drawline 1.6s var(--e-out) .2s forwards}
@keyframes drawline{to{stroke-dashoffset:0}}
.dchart .empty{margin:0;padding:var(--s6) 0;text-align:center;font-size:12px;color:var(--ink-3);border:0;background:none;box-shadow:none}
@media (max-width:600px){.dbars{gap:4px;height:130px}}

/* 손이 필요한 것 */
.todolist{margin-top:12px}
.todorow{display:flex;align-items:center;gap:var(--s3);width:100%;margin:0;padding:var(--s3) var(--s2);border:0;border-radius:12px;
  background:none;color:var(--ink);font-family:var(--font);font-size:13px;text-align:left;cursor:pointer;
  transition:background var(--t-fast)}
.todorow:hover{background:var(--surface-2)}
.todorow > span{flex:1;min-width:0}
.todorow b{font-size:14px;font-weight:600}
.todorow svg{width:14px;height:14px;color:var(--ink-3);flex:none}
.todorow .dot{width:7px;height:7px;border-radius:999px;flex:none;background:var(--ink-3);opacity:.5}
.todorow .dot.gold{background:var(--fill);opacity:1}
.todorow .dot.bad{background:var(--bad);opacity:1}
.todolist .empty{margin:0;padding:var(--s4) 0;font-size:12px;color:var(--ink-3);border:0;background:none;box-shadow:none;text-align:left}
.ratebox{border-top:1px solid var(--line);margin-top:var(--s4);padding-top:var(--s4)}
.ratebox .k{font-size:11px;color:var(--ink-3)}
.ratebox .rate{display:flex;align-items:baseline;gap:var(--s2);margin-top:var(--s2)}
.ratebox .big{font-family:var(--mono);font-size:25px;font-weight:500;letter-spacing:-.035em;color:var(--ink)}
.ratebox .u{font-size:12px;color:var(--ink-3)}
.ratebox .track{position:relative;height:5px;border-radius:999px;background:var(--bg-3);margin-top:var(--s3);overflow:visible}
.ratebox .track i{display:block;height:100%;border-radius:999px;background:var(--fill);transition:width .8s var(--e-out)}
.ratebox .track.over i{background:var(--bad)}
.ratebox .track em{position:absolute;top:-3px;bottom:-3px;width:2px;background:var(--ink);border-radius:2px}
.ratebox .note{font-size:10.5px;margin-top:var(--s2);color:var(--ink-3)}
.ratebox .note:empty{display:none}
.ratebox .note.bad{color:var(--bad)}
.ratebox .note.warn{color:var(--warn)}

/* 표 — 시안의 결 */
.tblwrap,.tw{border-radius:19px}
table th{font-size:11px;color:var(--ink-3);font-weight:500;padding:var(--s3) var(--s2);border-bottom:1px solid var(--line);white-space:nowrap}
table td{font-size:13px;padding:var(--s3) var(--s2);border-bottom:1px solid var(--line)}
table tr:last-child td{border-bottom:0}
table tbody tr{transition:background var(--t-fast)}
table tbody tr:hover td{background:var(--surface-2)}
.tw{background:var(--surface);border:1px solid var(--line);box-shadow:none}
.tw table thead th{padding:var(--s3) var(--s2)}
tbody td{box-shadow:none}

/* ===========================================================
   표면 v3 — 마이오피스 홈을 시안대로 (할 일 배너 · 큰 금액 · 네 칸 통계 ·
   두 단추 · 최근 7일 막대 · 준비 중 칩)
   =========================================================== */
.todo{display:flex;align-items:center;gap:var(--s3);width:100%;padding:var(--s3) var(--s4);border-radius:16px;
  background:var(--brand-bg);border:1px solid #E8D5A0;cursor:pointer;text-align:left;font-family:var(--font);color:var(--ink);
  transition:transform var(--t-fast) var(--e-spring),box-shadow var(--t-base)}
:root[data-theme="dark"] .todo{border-color:#4A3C1C}
.todo:hover{box-shadow:var(--sh-1)}
.todo:active{transform:scale(.99)}
.todo .ic{width:30px;height:30px;border-radius:10px;background:var(--fill);color:var(--on-accent);display:grid;place-items:center;flex:none}
.todo .ic svg{width:15px;height:15px}
.todo .tx{flex:1;min-width:0}
.todo b{display:block;font-size:13px;font-weight:600;letter-spacing:-.01em}
.todo small{display:block;font-size:11px;color:var(--ink-3);margin-top:2px;line-height:1.45}
.todo .chev{width:14px;height:14px;color:var(--ink-3);flex:none}

.greet h1{font-size:22px}
.amount .lab{font-size:12px;color:var(--ink-3);font-weight:500}
.amount .big{font-family:var(--mono);font-weight:500;letter-spacing:-.045em;font-size:clamp(38px,10vw,52px);line-height:1.05;margin-top:var(--s2)}
.amount .big small{font-family:var(--font);font-size:14px;color:var(--ink-3);font-weight:500;margin-left:var(--s2)}
.amount .delta{font-size:12px;margin-top:8px}

.trio{background:transparent;border:0;box-shadow:none;border-radius:0;padding:0;gap:var(--s3)}
.trio.quad{grid-template-columns:repeat(4,minmax(0,1fr))}
.trio.quad:has(> #mHeldBox:not(.hide)){grid-template-columns:repeat(5,minmax(0,1fr))}
.trio > div{text-align:left;padding:0;min-width:0}
.trio > div + div::before{display:none}
.trio .k{font-size:11px;color:var(--ink-3);margin-bottom:var(--s1);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.trio .v{font-family:var(--mono);font-size:14px;font-weight:500;letter-spacing:-.02em;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
@media (max-width:359px){.trio.quad,.trio.quad:has(> #mHeldBox:not(.hide)){grid-template-columns:repeat(2,minmax(0,1fr));row-gap:var(--s4)}}

.acts{display:grid;grid-template-columns:1fr 1fr;gap:var(--s3)}
.acts .btn{display:flex;align-items:center;justify-content:space-between;gap:var(--s2);padding:var(--s4) var(--s5);border-radius:15px;font-size:14px;font-weight:600;letter-spacing:-.015em;margin:0}
.acts .btn svg{width:16px;height:16px;flex:none;transition:transform var(--t-base) var(--e-out)}
.acts .btn:hover svg{transform:translateX(3px)}
.acts .btn.primary{box-shadow:0 1px 2px rgb(140 95 0/.22),0 6px 16px rgb(190 140 10/.2)}
.acts .btn.ghost{background:var(--pill);color:var(--ink);border:0}
.acts .btn.ghost:hover{background:var(--bg-3)}

.dchart.mini .dbars{height:120px;gap:8px}
.dchart.mini{margin-top:0;min-height:0}
.dchart.mini .dcol .n{font-size:10px}
.sechd .n{font-family:var(--mono);font-size:12px;color:var(--ink-2)}

.chip.mut{display:inline-block;font-size:10.5px;font-weight:600;padding:var(--s1) var(--s2);border-radius:999px;background:var(--pill);color:var(--ink-2);letter-spacing:-.01em}
.list .li.soft .k{color:var(--ink-3);font-size:12px;line-height:1.6;white-space:normal}

/* 좌·우 균형 — 시안 결: 조언은 노란 바탕 대신 흰 카드 안 한 줄 */
.advice{background:var(--surface);border:1px solid var(--line);border-radius:16px}
.advice .t{color:var(--ink);font-size:14px}
.advice.flat{background:var(--surface)}
.legs .one .v{font-family:var(--mono);font-weight:500}

/* ===========================================================
   표면 v3 — 마이오피스 PC 는 상단 내비 (시안). 어드민은 사이드바 그대로.
   구조(.shell > .side + main)는 그대로 두고 방향만 바꾼다 — JS 가 #nav 를 그대로 쓴다.
   =========================================================== */
@media (min-width:821px){
  body.my .shell{flex-direction:column}
  body.my .side{width:100%;flex-direction:row;align-items:center;gap:var(--s4);
    padding:0 var(--s6);height:64px;border-right:0;border-bottom:1px solid var(--line);
    position:sticky;top:0;z-index:40;background:color-mix(in srgb,var(--surface) 92%,transparent);
    -webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px)}
  body.my .side .brand{padding:0;gap:var(--s2);flex:none}
  body.my .side .brand strong{font-size:14px}
  body.my .side .brand em{display:none}
  body.my .side nav{flex:1;flex-direction:row;justify-content:center;gap:2px;padding:0;height:100%;align-items:stretch}
  body.my .side nav button{position:relative;padding:0 var(--s4);border-radius:0;font-size:14px;font-weight:500;color:var(--ink-3);
    display:inline-flex;align-items:center;transform:none}
  body.my .side nav button:hover{color:var(--ink);transform:none;background:transparent}
  body.my .side nav button.on{color:var(--ink);font-weight:600;background:transparent}
  body.my .side nav button.on::before{left:var(--s4);right:var(--s4);top:auto;bottom:0;width:auto;height:2px;margin:0;border-radius:2px 2px 0 0}
  body.my .side nav .navind{display:none}
  body.my .side .top{padding:0;gap:var(--s2);order:3;flex:none;flex-wrap:nowrap;row-gap:0}
  body.my .side .who{flex:none;max-width:160px}
  body.my .side .who{display:flex;flex-direction:column;align-items:flex-end;font-size:11px}
  body.my .side .who b{font-size:13px}
  body.my .side .sidefoot{display:none}
  body.my main{max-width:1120px;width:100%;margin:0 auto;padding:var(--s8) var(--s8) calc(var(--s5) + var(--support-h) + var(--s3))}
  body.my .hgrid{display:grid;grid-template-columns:1.55fr 1fr;gap:var(--s5);align-items:start}
}
.hgrid{display:flex;flex-direction:column;gap:var(--s5)}
.hcol{display:flex;flex-direction:column;gap:var(--s5);min-width:0}
.hcol .sec{margin:0}
.hcol > .prog{margin-bottom:0}
.hcol .sec h2{margin-top:0}

/* 수당 내역 — 월 머리(금색 점 · 「2026년 9월」 · 건수·합계), 흰 바탕. 띠 배경 없음 */
.mhead{display:flex;align-items:center;gap:var(--s3);padding:var(--s5) var(--s0) var(--s2);font-size:13px}
.mhead i{width:7px;height:7px;border-radius:999px;background:var(--fill);flex:none}
.mhead b{font-weight:600;letter-spacing:-.015em;color:var(--ink)}
.mhead .n{margin-left:auto;font-family:var(--mono);font-size:11.5px;color:var(--ink-3)}
.mhead + .rows{margin-top:0}
#commList > .mhead:first-child{padding-top:0}
.pager{justify-content:space-between;margin-top:var(--s4);font-size:12px;color:var(--ink-3)}
.pager .pg{display:flex;align-items:center;gap:var(--s2)}
.pager .pg b{font-family:var(--mono);font-weight:500;color:var(--ink-2);padding:0 var(--s1);font-size:12px}
.pager .btn.sm{width:32px;height:32px;padding:0;border-radius:10px;border:1px solid var(--line-2);background:transparent;color:var(--ink-2);font-size:14px;display:inline-grid;place-items:center;min-height:0}
.pager .btn.sm:hover{background:var(--pill)}
.pager .btn.sm[disabled]{opacity:.4}
.rows{background:var(--surface);border:1px solid var(--line);border-radius:19px}
.rows .r + .r{box-shadow:inset 0 1px 0 var(--line)}
.rows .r{padding:var(--s3) var(--s4)}
.rows .t{font-size:13px;font-weight:500}
.rows .t.num{font-family:var(--mono);font-weight:500;font-size:14px}
.rows .r:hover{background:var(--surface-2)}
/* 수당 조정의 사유 — 관리자가 적은 문장을 회원에게 그대로 */
.rows .s .memo{display:block;margin-top:var(--s1);color:var(--ink-2);white-space:normal;line-height:var(--lh-snug)}

/* 조직도 정보 카드 — PC 는 트리 오른쪽, 모바일은 **트리 박스 바로 아래**(시트가 아니다).
   누른 뒤 화면이 움직이지 않는다 — 카드는 아래에 생기고 트리는 그대로 만질 수 있다. */
.treeside{background:var(--surface);border:1px solid var(--line);border-radius:19px;padding:var(--s5)}
@media (max-width:820px){
  .treeside{position:relative;left:auto;right:auto;bottom:auto;z-index:auto;
    max-height:none;border-radius:19px;border:1px solid var(--line);box-shadow:none;
    margin-top:var(--s4);padding:var(--s5);animation:cardRise var(--t-base) var(--e-out) backwards}
  .treeside .sideclose{position:absolute;right:var(--s3);top:var(--s3)}
}
@keyframes cardRise{from{opacity:0;transform:translateY(8px)}}
.orgsum{gap:var(--s3)}
.orgsum > div{background:var(--surface);border:1px solid var(--line);border-radius:17px;padding:var(--s3) var(--s4)}
.orgsum .v{font-family:var(--mono);font-weight:500}
#orgLegs{background:var(--surface);border:1px solid var(--line);border-radius:19px;padding:var(--s5)}
.treebox{background:var(--surface);border:1px solid var(--line);border-radius:19px}
.trio:has(> #wHeldBox.hide){grid-template-columns:repeat(2,1fr)}

/* ===========================================================
   슬라이드오버 · 바텀시트 (lib.js slideOver) · 일괄 작업 바
   =========================================================== */
.sheethost{position:fixed;inset:0;z-index:70;pointer-events:none}
.sheethost .sheetscrim{position:absolute;inset:0;background:rgb(12 10 6/.42);opacity:0;
  transition:opacity var(--t-base) var(--e-out);pointer-events:auto;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}
.sheethost.in .sheetscrim{opacity:1}
.sheethost.out .sheetscrim{opacity:0}
.sheethost .sheet{position:absolute;left:0;right:0;bottom:0;max-height:88dvh;display:flex;flex-direction:column;
  background:var(--surface);border-radius:26px 26px 0 0;box-shadow:var(--sh-3);pointer-events:auto;
  transform:translateY(100%);transition:transform 420ms var(--e-spring)}
.sheethost.in .sheet{transform:none}
.sheethost.out .sheet{transform:translateY(100%);transition:transform 240ms var(--e-inout)}
.sheethost .grab{display:block;width:40px;height:5px;border-radius:999px;background:var(--line-2);margin:var(--s3) auto 0}
.sheethost .hd{display:flex;align-items:flex-start;gap:var(--s3);padding:var(--s4) var(--s5) var(--s3)}
.sheethost .hdt{flex:1;min-width:0}
.sheethost .hd h3{margin:0;font-size:16px;font-weight:600;letter-spacing:-.02em}
.sheethost .hd small{display:block;font-size:11px;color:var(--ink-3);margin-top:var(--s1)}
.sheethost .bd{overflow-y:auto;padding:var(--s1) var(--s5) var(--s6);min-height:0}
.iconbtn{width:36px;height:36px;border:0;border-radius:12px;background:var(--pill);color:var(--ink-2);display:grid;place-items:center;cursor:pointer;flex:none;
  transition:background var(--t-fast),transform var(--t-fast) var(--e-spring)}
.iconbtn:hover{background:var(--bg-3)}
.iconbtn:active{transform:scale(.93)}
.iconbtn svg{width:18px;height:18px}
@media (min-width:821px){
  .sheethost .sheetscrim{display:none}
  .sheethost .sheet{left:auto;top:0;bottom:0;width:440px;max-height:none;border-radius:0;border-left:1px solid var(--line);
    transform:translateX(100%);transition:transform 380ms var(--e-out)}
  .sheethost.out .sheet{transform:translateX(100%)}
  .sheethost .grab{display:none}
  .sheethost .hd{padding:var(--s6) var(--s6) var(--s3)}
  .sheethost .bd{padding:var(--s1) var(--s6) var(--s6)}
}
/* 시트 안 — 키·값 줄 */
.kvl{display:flex;justify-content:space-between;gap:var(--s4);padding:var(--s2) 0;border-bottom:1px solid var(--line);font-size:13px}
.kvl:last-child{border-bottom:0}
.kvl > span{color:var(--ink-3);flex:none}
.kvl > b{font-weight:500;text-align:right;min-width:0;word-break:break-all}
.kvl > b.n{font-family:var(--mono)}
.sheetacts{display:flex;flex-wrap:wrap;gap:var(--s2);margin-top:var(--s4)}
.sheetacts .btn{flex:1 1 auto}
/* 회원 카드 아래 — 잠금 배지 한 줄 + 고치러 가는 단추들 (43단계) */
.treeacts{margin-top:var(--s4);padding-top:var(--s4);border-top:1px solid var(--line);
  display:flex;flex-direction:column;gap:var(--s3)}
.treeacts:empty{display:none}
.tag.lk{white-space:nowrap}
.treeacts .lockline{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2);
  font-size:var(--fs-xs);color:var(--ink-3);line-height:1.5}
.treeacts .btn[disabled]{opacity:.45;cursor:not-allowed}
#fxPurgeNote[hidden]{display:none}
/* 누를 수 있는 줄 */
tr.pickrow{cursor:pointer}
tr.pickrow:hover td{background:var(--surface-2)}
tr.pickrow.sel td{background:var(--brand-bg)}

/* 일괄 작업 바 — 고른 것이 있을 때만 아래에 떠 있다 (표는 안 밀린다) */
.bulkbar{position:fixed;left:50%;bottom:calc(var(--s5) + env(safe-area-inset-bottom,0px));transform:translate(-50%,120%);
  display:flex;align-items:center;gap:var(--s3);padding:var(--s3) var(--s3) var(--s3) var(--s5);border-radius:18px;z-index:55;
  background:var(--ink);color:var(--ground);box-shadow:var(--sh-3);font-size:13px;max-width:calc(100% - var(--s8));
  transition:transform var(--t-base) var(--e-spring),opacity var(--t-base);opacity:0;pointer-events:none}
.bulkbar.on{transform:translate(-50%,0);opacity:1;pointer-events:auto}
.bulkbar b{font-family:var(--mono);font-weight:500}
.bulkbar .sum{color:color-mix(in srgb,var(--ground) 70%,transparent);font-family:var(--mono);font-size:12px}
.bulkbar .btn.sm{min-height:0;padding:var(--s2) var(--s3);border-radius:11px}
.bulkbar .btn.ghost{background:color-mix(in srgb,var(--ground) 14%,transparent);color:var(--ground);border:0}
@media (max-width:820px){.bulkbar{bottom:calc(var(--tabbar-h,64px) + var(--s4) + env(safe-area-inset-bottom,0px));width:calc(100% - var(--s6));justify-content:space-between;flex-wrap:wrap}}

/* ===========================================================
   표면 v3 — 어드민 본문은 늘 끝까지(장마다 여백이 달랐다) · 폼은 라벨 위,
   입력 아래(시안 .field) · 두 기둥 .g11 · 공지 미리보기
   =========================================================== */
body.ad main{max-width:none}

/* ⚠️ 아래 정렬은 라벨+칸이 있는 줄에서만 — 단추·딱지·안내문만 있는 줄은 가운데(.row 기본). 2026-10-23 */
.row.wrap{gap:var(--s3)}
.row.wrap:has(> label:not(.chk) > :is(input:not([type=checkbox]):not([type=radio]),select,textarea,.selbox,.datebox,.picker)){align-items:flex-end}
.row label:not(.chk){flex-direction:column;align-items:stretch;gap:var(--s2);min-width:min(100%,160px)}
.row label:not(.chk) > span:not(.selbox):not(.picker):not(.seg):not(.datebox){font-size:11px;font-weight:500;color:var(--ink-3);white-space:nowrap}
.row label:not(.chk) > input,.row label:not(.chk) > select,.row label:not(.chk) > textarea{width:100%;min-width:0;margin:0;
  padding:var(--s3);border-radius:11px;font-size:13px;background:var(--ground);border:1px solid var(--line-2);color:var(--ink);font-family:var(--font)}
.row label:not(.chk) > textarea{resize:vertical;line-height:1.5;min-height:72px}
.row label:not(.chk) > input:focus,.row label:not(.chk) > textarea:focus{outline:none;border-color:var(--fill);box-shadow:0 0 0 3px var(--brand-bg)}
/* 라벨이 세로(이름 위 · 칸 아래)가 되면서, 라벨이 없는 형제(세그먼트·단추·안내문·홀로 선 선택칸)는
   **칸**에 맞춰야지 라벨+칸 덩어리의 가운데에 맞추면 안 된다 — 그러면 이름 글자 높이의 절반만큼
   위로 뜬다(조직도의 후원/추천 세그먼트가 실제로 그랬다). 아래로 붙이고 칸과 같은 높이를 준다.
   ⚠️ 이건 **라벨+칸이 있는 줄에서만**이다. 딱지·안내문·단추만 있는 줄(2단계 인증의 「켜짐 · 2026-10-01 부터 ·
   백업 코드 8개 남음」 같은)에 똑같이 적용하면 안내문만 45px 로 커져 아래로 붙고 딱지는 가운데 남아 서로
   어긋난다 — 실제로 그랬다(2026-10-23). 칸이 있는 줄만 :has() 로 골라낸다. */
.row{--field-h:45px}
.row label:not(.chk) > input:not([type=checkbox]):not([type=radio]),.row label:not(.chk) > select{min-height:var(--field-h)}
/* 체크 라벨도 **칸**에 맞춘다 — 가운데+아래여백은 칸 중심보다 13px 위로 떴다(수당 조정의 「500% 한도에도 반영」) */
.row:has(> label:not(.chk) > :is(input:not([type=checkbox]):not([type=radio]),select,textarea,.selbox,.datebox,.picker)) label.chk{align-self:flex-end;min-height:var(--field-h);padding-bottom:0}
.row:has(> label:not(.chk) > :is(input:not([type=checkbox]):not([type=radio]),select,textarea,.selbox,.datebox,.picker)) > .btn{align-self:flex-end}
.row:has(> label:not(.chk) > :is(input:not([type=checkbox]):not([type=radio]),select,textarea,.selbox,.datebox,.picker)) > :is(.seg,.note,.msg,.selbox,.picker,.datebox){
  align-self:flex-end;min-height:var(--field-h);display:inline-flex;align-items:center}
/* 칸 없는 줄: 전부 가운데 정렬, 안내문·메시지는 위 여백 없이 */
.row > .msg,.row > .note{margin:0}
.row > .msg:empty,.row > .note:empty{display:none}
.row label:not(.chk) > .selbox .selbtn,.row label:not(.chk) > .datebox{border-radius:11px;background:var(--ground);border-color:var(--line-2)}
.card.panel h3,.card.panel .sect{margin:0}
.card.panel .sectsub{margin:var(--s1) 0 var(--s4)}
.card.panel .row{margin:var(--s3) 0 0}

.g11{display:grid;grid-template-columns:1fr 1fr;gap:var(--s4);align-items:start}
@media (max-width:900px){.g11{grid-template-columns:1fr}}
.g11 > .stack{display:flex;flex-direction:column;gap:var(--s4)}

.pushpv{background:var(--ground);border:1px solid var(--line);border-radius:22px;padding:var(--s4);max-width:320px;margin-top:var(--s3)}
.pushpv-hd{display:flex;justify-content:space-between;font-size:10px;color:var(--ink-3);margin-bottom:var(--s2)}
.pushpv-t{font-size:13px;font-weight:600;line-height:1.5}
.pushpv-b{font-size:12px;color:var(--ink-2);margin-top:var(--s1);line-height:1.5;word-break:break-word}
.pushpv-b.mute{color:var(--ink-3)}
.row label:not(.chk):not(.grow){flex:1 1 180px;max-width:min(100%,320px)}
.g11 > *,.g11 > .stack > *{min-width:0}
.row label.grow{max-width:none}
.g11 > .stack.stack{gap:var(--s4)}
/* 페이지 머리 — 제목 옆 설명은 짧게, 오른쪽에 주 작업 하나 */
.pagehd > div:first-child{min-width:0;flex:1 1 320px}
.pagehd .pagesub{max-width:72ch}
.pagehd + .subnav,.pagehd + .seg{margin-top:var(--s4)}
.formcard[hidden]{display:none}
.pagehd-act .btn.primary.sm{display:inline-flex;align-items:center;gap:var(--s1)}
/* ⚠️ 라벨이 세로(column)가 되면서 .picker/.selbox 의 flex-basis(160·180px)가 **높이**로 먹었다.
   칸이 160px 짜리 빈 상자가 되고 펼친 목록이 그 아래서 시작해 화면 밖으로 나갔다. 가로폭만 채운다. */
.row label:not(.chk) > .picker,.row label:not(.chk) > .selbox{flex:none;width:100%;min-width:0}

/* ── 공지 보내기: 이미지 놓는 자리 · 받는 회원 칩 · 미리보기 ── */
.drop{display:block;border:1.5px dashed var(--line-2);border-radius:14px;background:var(--ground);cursor:pointer;position:relative;
  transition:border-color var(--t-fast),background var(--t-fast)}
.drop:hover,.drop.over{border-color:var(--fill);background:var(--brand-bg)}
.drop:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.drop-empty{display:flex;flex-direction:column;align-items:center;gap:var(--s1);padding:var(--s5) var(--s4);text-align:center;color:var(--ink-3)}
.drop-empty svg{width:26px;height:26px;color:var(--ink-3);margin-bottom:var(--s1)}
.drop-empty b{font-size:13px;font-weight:600;color:var(--ink-2)}
.drop-empty small{font-size:11px;line-height:1.5}
.drop-has{display:flex;flex-direction:column;gap:var(--s2);padding:var(--s3)}
.drop-has img{display:block;max-width:100%;max-height:260px;width:auto;height:auto;margin:0 auto;border-radius:10px}
.drop-meta{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);font-size:11px;color:var(--ink-3)}
.drop-busy{position:absolute;inset:0;display:grid;place-items:center;background:color-mix(in srgb,var(--surface) 80%,transparent);border-radius:14px;font-size:12px;color:var(--ink-2)}
.drop-busy.hide,.drop-has.hide,.drop-empty.hide{display:none}
.chips{display:flex;flex-wrap:wrap;gap:var(--s2);margin-top:var(--s3)}
.chips:empty{display:none}
.chipm{display:inline-flex;align-items:center;gap:var(--s2);padding:var(--s1) var(--s1) var(--s1) var(--s3);border-radius:999px;background:var(--brand-bg);color:var(--ink);font-size:12px;
  animation:chipIn var(--t-base) var(--e-spring) backwards}
@keyframes chipIn{from{opacity:0;transform:scale(.8)}}
.chipm b{font-weight:600}
.chipm code{font-size:11px;color:var(--accent);background:transparent;padding:0}
.chipm button{width:22px;height:22px;border:0;border-radius:999px;background:transparent;color:var(--ink-3);cursor:pointer;font-size:14px;line-height:1;display:grid;place-items:center}
.chipm button:hover{background:var(--fill);color:var(--on-accent)}
#ntNoticeWho.warn{color:var(--warn)}
.pvpanel .sectsub{margin-top:var(--s4)}
.inboxpv{display:flex;gap:var(--s3);padding:var(--s3) var(--s4);border:1px solid var(--line);border-radius:16px;background:var(--surface);max-width:360px}
.inboxpv.small{max-width:none;margin-top:var(--s3)}
.inboxpv-ic{width:34px;height:34px;border-radius:11px;background:var(--brand-bg);color:var(--accent);display:grid;place-items:center;flex:none}
.inboxpv-ic svg{width:17px;height:17px}
.inboxpv-b{flex:1;min-width:0}
.inboxpv-t{font-size:13px;font-weight:600;letter-spacing:-.01em;line-height:1.45}
.inboxpv-img{display:block;width:100%;height:auto;border-radius:10px;margin-top:var(--s2)}
.inboxpv-img.hide{display:none}
.inboxpv-x{font-size:12.5px;color:var(--ink-2);line-height:1.55;margin-top:var(--s1);white-space:pre-wrap;word-break:break-word}
.inboxpv-x.mute,.pushpv-b.mute{color:var(--ink-3)}
.inboxpv-d{font-size:11px;color:var(--ink-3);margin-top:var(--s2)}

/* 회원 알림함 — 공지는 제목·그림을 가진다 */
.noti .n .x{font-size:13px;color:var(--ink-2);line-height:1.55;margin-top:var(--s1);white-space:pre-wrap;word-break:break-word}
.noti .n .pic{display:block;width:100%;max-width:420px;height:auto;border-radius:12px;margin-top:var(--s2)}
/* ⚠️ 알림함의 줄도 .n 이라 숫자용 모노 글꼴 규칙에 걸렸다 — 글은 본문 글꼴로 */
.noti .n{font-family:var(--font);font-weight:400}
.noti .n .t{font-weight:600;letter-spacing:-.01em}
.noti .n .d{font-family:var(--mono)}
.drop{max-width:100%;min-width:0;box-sizing:border-box}
.drop-empty{min-width:0;max-width:100%}
.drop-empty small,.drop-empty b{max-width:100%;overflow-wrap:anywhere}
.row label.grow > .drop{width:100%}
.drop,.drop *{white-space:normal}
.drop{font-size:12px;font-weight:400;color:var(--ink-2)}
/* 회원 찾기 목록 — 이름 · 아이디 · 회원코드 세 칸 */
.pickmenu button b{flex:none;font-weight:600}
.pickmenu button .lid{flex:1;min-width:0;font-family:var(--mono);font-size:12px;color:var(--accent);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pickmenu button code{flex:none;font-family:var(--mono)}

/* ── 은행 고르기 ── */
.bankbtn{display:flex;align-items:center;gap:var(--s2);width:100%;min-height:46px;padding:var(--s2) var(--s3);border-radius:11px;
  background:var(--ground);border:1px solid var(--line-2);color:var(--ink);font-family:var(--font);font-size:13px;cursor:pointer;text-align:left;
  transition:border-color var(--t-fast),box-shadow var(--t-fast)}
.bankbtn:hover{border-color:var(--fill)}
.bankbtn:focus-visible{outline:none;border-color:var(--fill);box-shadow:0 0 0 3px var(--brand-bg)}
.bankbtn img{width:24px;height:24px;border-radius:999px;flex:none}
.bankbtn > span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bankbtn .ph{color:var(--ink-3)}
.bankbtn i{font-style:normal;color:var(--ink-3);font-size:16px;line-height:1;flex:none;transform:rotate(90deg)}
.row label:not(.chk) > .bankbtn{width:100%}
.bankhd{display:flex;flex-direction:column;gap:var(--s3);padding-bottom:var(--s3);position:sticky;top:0;background:var(--surface);z-index:1}
.bankhd .seg{display:inline-flex;background:var(--surface-2);border:1px solid var(--hair);border-radius:12px;padding:var(--s1);gap:var(--s0)}
.bankhd .seg button{flex:1;border:0;background:transparent;color:var(--ink-3);font-family:var(--font);font-size:13px;font-weight:500;padding:var(--s2) var(--s3);border-radius:8px;cursor:pointer;
  transition:color var(--t-fast),background var(--t-fast)}
.bankhd .seg button[aria-pressed="true"]{background:var(--seg-sel);color:var(--ink);font-weight:600;box-shadow:0 0 0 1px var(--hair),var(--sh-1)}
.banksearch{display:flex;align-items:center;gap:var(--s2);margin:0;padding:0 var(--s3);height:40px;border:1px solid var(--line-2);border-radius:11px;background:var(--ground)}
.banksearch svg{width:15px;height:15px;color:var(--ink-3);flex:none}
.banksearch input{flex:1;min-width:0;border:0;background:transparent;outline:0;font-family:var(--font);font-size:13px;color:var(--ink);padding:0;margin:0}
.bankgrid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s2)}
.bankcell{display:flex;flex-direction:column;align-items:center;gap:var(--s2);padding:var(--s4) var(--s2) var(--s3);border:1px solid var(--line);border-radius:16px;
  background:var(--surface);color:var(--ink);font-family:var(--font);font-size:12px;cursor:pointer;min-width:0;
  transition:transform var(--t-fast) var(--e-spring),border-color var(--t-fast),background var(--t-fast)}
.bankcell img{width:40px;height:40px;border-radius:999px}
.bankcell span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;letter-spacing:-.01em}
.bankcell:hover{border-color:var(--line-2);background:var(--surface-2)}
.bankcell:active{transform:scale(.96)}
.bankcell.on{border-color:var(--fill);background:var(--brand-bg);font-weight:600}
.bankcell:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.bankgrid .empty{grid-column:1/-1;margin:0;padding:var(--s6) 0;text-align:center;font-size:12px;color:var(--ink-3);border:0;background:none;box-shadow:none}
@media (max-width:360px){.bankgrid{grid-template-columns:repeat(3,minmax(0,1fr))}.bankcell{font-size:11px}}

/* 조직도 양옆 흐림(moreL/moreR)은 지운다 — 상자가 흰색이 되면서 베이지 덩어리로 보였다.
   잘림은 배율 단추·끌기·미니 크기로 충분히 드러난다. 클래스는 그대로 두어 검사(잘림표시없음)는 지난다. */
.treewrap.moreL::before,.treewrap.moreR::after{display:none}
/* 조직도 정보 카드 안 목록 — 테두리가 생긴 뒤로 글자가 선에 붙었다 */
.treeside .list .li{padding:var(--s2) var(--s3)}
.treeside .list{background:var(--surface);border:1px solid var(--line)}
/* 은행 아이콘 — 스프라이트 한 칸. 8열이라 background-size 는 800% */
.bkic{display:inline-block;width:40px;height:40px;border-radius:999px;flex:none;
  background-image:url(/banks.png);background-repeat:no-repeat;background-size:800% auto}
.bankbtn .bkic{width:24px;height:24px}
.bankcell .bkic{width:40px;height:40px}

/* ── 수당 내역 거르기 (2026-10 다시 설계) ──
   한 줄 종류 칩(옆으로 넘김) → 기간 단추 하나(+ 걸렸을 때만 초기화) → 펼치면 기간 판 */
.filter{gap:var(--s3)}
.chiprow{display:flex;gap:var(--s2);overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch;padding-bottom:var(--s1);
  margin-inline:calc(-1 * var(--s4));padding-inline:var(--s4);scroll-padding-inline:var(--s4)}
.chiprow::-webkit-scrollbar{display:none}
@media (min-width:821px){.chiprow{margin-inline:0;padding-inline:0;flex-wrap:wrap}}
.chip{background:var(--surface);border-color:var(--line-2);color:var(--ink-2);padding:var(--s2) var(--s3);font-size:13px}
.chip.on{background:var(--ink);color:var(--ground);border-color:var(--ink)}
.rangebar{display:flex;align-items:center;gap:var(--s2)}
.rangebtn{display:inline-flex;align-items:center;gap:var(--s2);padding:var(--s2) var(--s3);min-height:40px;border-radius:11px;
  background:var(--surface);border:1px solid var(--line-2);color:var(--ink);font-family:var(--font);font-size:13px;font-weight:500;cursor:pointer;
  transition:border-color var(--t-fast),background var(--t-fast)}
.rangebtn svg{width:16px;height:16px;color:var(--ink-3);flex:none}
.rangebtn i{font-style:normal;color:var(--ink-3);font-size:15px;line-height:1;transform:rotate(90deg);transition:transform var(--t-base) var(--e-out)}
.rangebtn[aria-expanded="true"] i{transform:rotate(-90deg)}
.rangebtn:hover{border-color:var(--fill)}
.rangebtn.on{background:var(--brand-bg);border-color:#E8D5A0;color:var(--accent)}
.rangebtn.on svg{color:var(--accent)}
.clearbtn{display:inline-flex;align-items:center;gap:var(--s1);border:0;background:transparent;color:var(--ink-3);font-family:var(--font);font-size:12px;
  padding:var(--s2) var(--s2);border-radius:10px;cursor:pointer;min-height:40px}
.clearbtn:hover{background:var(--pill);color:var(--ink)}
.clearbtn.hide{display:none}
.rangepanel{max-width:560px;background:var(--surface);border:1px solid var(--line);border-radius:14px;padding:var(--s3) var(--s4) var(--s4);display:flex;flex-direction:column;gap:var(--s3);
  box-shadow:var(--sh-2);animation:cardRise var(--t-base) var(--e-out) backwards}
.rangepanel.hide{display:none}
/* 자주 쓰는 기간은 종류 칩과 같은 한 줄 — 좁으면 옆으로 넘긴다. 두 줄로 접히면 판이 무거워진다 */
.rangepanel .quickdates{padding-bottom:0}
.rangepanel .daterow{display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);gap:var(--s2);align-items:end}
.rangepanel .daterow label{display:flex;flex-direction:column;gap:var(--s1);margin:0;min-width:0;font-size:11px;color:var(--ink-3);font-weight:500}
.rangepanel .daterow .datebox,.rangepanel .daterow input{width:100%;min-width:0}
.rangepanel .daterow .datebtn{min-width:0;width:100%;padding-inline:var(--s3)}
/* 칸이 둘 나란히라 좁은 폰에서 날짜가 두 줄로 꺾였다 — 달력 아이콘은 빼고(두 칸 모두 날짜인 게 자명하다) 한 줄로 */
.rangepanel .daterow .datebtn .selcaret{display:none}
.rangepanel .daterow .datebtn .sellab{white-space:nowrap;font-variant-numeric:tabular-nums}
.rangepanel .daterow .tilde{font-style:normal;color:var(--ink-3);font-size:14px;line-height:1;display:flex;align-items:center;height:45px;align-self:end}
/* 두 번째 칸의 달력은 오른쪽에 건다 — 왼쪽에 걸면 판 밖으로 나간다 */
.rangepanel .daterow label:last-of-type .datemenu{left:auto;right:0}
.filter:not(.active) .daterow .btn{opacity:1;pointer-events:auto}

/* 세로 라벨 안에 들어가는 안내 한 줄(아이디 중복 확인) — 라벨 캡션 규칙을 이기고 제 색을 낸다 */
.row label:not(.chk) > .fldnote.inrow{margin:0;white-space:normal;font-size:11px}
.fldnote.inrow:empty{display:none}
.row label:not(.chk) > .fldnote.inrow.ok{color:var(--ok)}
.row label:not(.chk) > .fldnote.inrow.no{color:var(--bad)}
