
:root{
  --tk-blue:#004bff; --tk-blue-deep:#0024ed; --tk-ink:#11151f;
  --tk-gray-50:#f5f7fa; --tk-gray-200:#e5e7eb; --tk-gray-500:#6b7280; --tk-tint:#e0e7ff;
  
  --brand:var(--tk-blue); --brand-deep:var(--tk-blue-deep); --tint:var(--tk-tint);
  --bg-page:#fff; --bg-subtle:var(--tk-gray-50); --surface-card:#fff; --surface-elevated:#fff;
  --text-primary:var(--tk-ink); --text-secondary:var(--tk-gray-500); --text-brand:var(--tk-blue);
  --border-subtle:var(--tk-gray-200);
  --state-up:#16A34A; --state-down:#DC2626; --state-warning:#F59E0B; --state-info:#0EA5E9;
  --on-brand:#fff;
  --focus-ring:rgba(0,75,255,.12);
  --shadow-card:0 1px 2px rgba(17,21,31,.04),0 2px 8px rgba(17,21,31,.04);
  --shadow-card-hover:0 2px 8px rgba(17,21,31,.05),0 2px 4px rgba(17,21,31,.04);
  /* Google 로그인 버튼 — 공식 가이드라인의 흰 버튼(#fff/#3c4043/#dadce0) */
  --google-btn-bg:#fff; --google-btn-fg:#3c4043; --google-btn-border:#dadce0; --google-btn-hover:#f8f9fb;

  --font-sans:-apple-system,BlinkMacSystemFont,system-ui,sans-serif;
  --font-mono:ui-monospace,"SF Mono",Menlo,Consolas,monospace;
  --radius-md:10px; --radius-lg:16px; --radius-pill:999px;
  --ease:cubic-bezier(.22,1,.36,1);
  /* 8px 그리드 — 리터럴 px 를 섞지 않는다 (브리프 §6.2-5) */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s6:24px; --s8:32px; --s12:48px;
  /* 콘솔 셸 치수 — 상단바 높이는 사이드바 sticky 오프셋으로도 쓰인다(한 값만 고친다) */
  --top-h:56px; --side-w:216px;
  color-scheme:light dark;
}
/* 다크에서는 그림자 대신 레이어 밝기로 층을 만든다 — 어두운 배경에 검은 그림자는 보이지 않는다 */
@media (prefers-color-scheme: dark){ :root{
  --brand:#B3CCFF; --brand-deep:#d6e4ff; --tint:#1e2a4a;
  --bg-page:#0c1017; --bg-subtle:#161b27; --surface-card:#1a1f2e; --surface-elevated:#333e5c;
  --text-primary:#ffffff; --text-secondary:#9ca3af; --text-brand:#B3CCFF;
  --border-subtle:#262c3a;
  --state-up:#4ADE80; --state-down:#F87171; --state-warning:#FBBF24; --state-info:#38BDF8;
  --on-brand:#11151f;
  --focus-ring:rgba(179,204,255,.12);
  --shadow-card:none; --shadow-card-hover:none;
  /* Google 로그인 버튼 — 공식 다크 변형(#131314/#5f6368). 흰 버튼을 다크에 그대로 두면 혼자 빛난다 */
  --google-btn-bg:#131314; --google-btn-fg:#e3e3e3; --google-btn-border:#5f6368; --google-btn-hover:#1f2023;
} }
/* 사용자가 고른 값이 시스템 설정을 이긴다 — 양방향 모두 명시해야 되돌리기가 된다 */
:root[data-theme="dark"]{
  --brand:#B3CCFF; --brand-deep:#d6e4ff; --tint:#1e2a4a;
  --bg-page:#0c1017; --bg-subtle:#161b27; --surface-card:#1a1f2e; --surface-elevated:#333e5c;
  --text-primary:#ffffff; --text-secondary:#9ca3af; --text-brand:#B3CCFF;
  --border-subtle:#262c3a;
  --state-up:#4ADE80; --state-down:#F87171; --state-warning:#FBBF24; --state-info:#38BDF8;
  --on-brand:#11151f;
  --focus-ring:rgba(179,204,255,.12);
  --shadow-card:none; --shadow-card-hover:none;
  /* Google 로그인 버튼 — 공식 다크 변형(#131314/#5f6368). 흰 버튼을 다크에 그대로 두면 혼자 빛난다 */
  --google-btn-bg:#131314; --google-btn-fg:#e3e3e3; --google-btn-border:#5f6368; --google-btn-hover:#1f2023;
}
:root[data-theme="light"]{
  --brand:var(--tk-blue); --brand-deep:var(--tk-blue-deep); --tint:var(--tk-tint);
  --bg-page:#fff; --bg-subtle:var(--tk-gray-50); --surface-card:#fff; --surface-elevated:#fff;
  --text-primary:var(--tk-ink); --text-secondary:var(--tk-gray-500); --text-brand:var(--tk-blue);
  --border-subtle:var(--tk-gray-200);
  --state-up:#16A34A; --state-down:#DC2626; --state-warning:#F59E0B; --state-info:#0EA5E9;
  --on-brand:#fff;
  --focus-ring:rgba(0,75,255,.12);
  --shadow-card:0 1px 2px rgba(17,21,31,.04),0 2px 8px rgba(17,21,31,.04);
  --shadow-card-hover:0 2px 8px rgba(17,21,31,.05),0 2px 4px rgba(17,21,31,.04);
  /* Google 로그인 버튼 — 공식 가이드라인의 흰 버튼(#fff/#3c4043/#dadce0) */
  --google-btn-bg:#fff; --google-btn-fg:#3c4043; --google-btn-border:#dadce0; --google-btn-hover:#f8f9fb;
}

*{box-sizing:border-box}
/* 한국어는 어절 단위로 끊어야 읽힌다. 기본값(break-word)은 "함께 쓰|는" 처럼 낱말을 쪼갠다. */
body{word-break:keep-all;overflow-wrap:break-word}
/* 단, 주소·코드는 길어서 어절 규칙을 적용하면 넘친다 — 여기서만 되돌린다. */
.addr,.item-slug,code,pre{word-break:break-all}
/* 콘솔 셸이 스스로 여백을 잡는다 — body 에 max-width 를 두면 사이드바가 화면 끝에 붙지 않는다. */
body{margin:0;font-family:var(--font-sans);font-size:16px;line-height:1.6;color:var(--text-primary);
  background:var(--bg-page);-webkit-font-smoothing:antialiased;padding:0}
::selection{background:var(--brand);color:var(--on-brand)}
a{color:var(--brand);text-decoration:none} a:hover{opacity:.8}
h1{font-size:40px;font-weight:700;letter-spacing:-.02em;color:var(--text-brand);margin:0 0 var(--s1)}
h2{font-size:24px;font-weight:600;letter-spacing:-.02em;margin:var(--s8) 0 var(--s3)}
h3{font-size:20px;font-weight:600;margin:var(--s4) 0 var(--s2)}
.sub{color:var(--text-secondary);margin:0 0 var(--s6)}
.home{text-decoration:none;color:inherit}

.card{background:var(--surface-card);border:1px solid var(--border-subtle);border-radius:var(--radius-lg);
  box-shadow:var(--shadow-card);padding:var(--s6);margin:var(--s3) 0;transition:box-shadow .15s var(--ease),border-color .15s var(--ease)}
.card:hover{box-shadow:var(--shadow-card-hover);border-color:var(--brand)}
/* 폼 전용 카드 — 입력은 520px 인데 카드가 화면 폭을 다 쓰면 오른쪽이 통째로 빈다
   (육안 검수 2026-08-27, 항목 추가·수정 전용 페이지). 폼 폭 + 좌우 여백에 맞춘다. */
.card-form{max-width:572px}
.card-title{font-size:16px;font-weight:600;letter-spacing:-.02em;color:var(--text-primary)}
.card-title a{color:var(--text-primary)} .card-title a:hover{color:var(--brand);opacity:1}
.card-title-lg{font-size:20px}
.card-desc{font-size:14px;color:var(--text-secondary);margin-top:var(--s1)}
.card-desc-lg{font-size:15px}
.mt2{margin-top:var(--s2)} .mt3{margin-top:var(--s3)} .mb3{margin-bottom:var(--s3)}
.push{margin-left:auto}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:var(--s3)}

.badge{display:inline-flex;align-items:center;gap:6px;height:24px;padding:0 10px;border-radius:var(--radius-pill);white-space:nowrap;
  font-size:12px;font-weight:500;line-height:1;vertical-align:middle}
.badge-neutral{background:var(--bg-subtle);color:var(--text-secondary);border:1px solid var(--border-subtle)}
.badge-brand{background:var(--brand);color:var(--on-brand)}
.badge-tint{background:var(--tint);color:var(--brand)}
/* 값(등급·전송 방식)을 담는 배지. 문장 배지와 모양으로 구분돼 스캔이 빠르다. */
.badge-mono{font-family:var(--font-mono);font-size:11px;height:22px;padding:0 9px}

/* 버튼 라벨은 줄바꿈하지 않는다 — 툴바가 좁아지면 "분류 관리"가 두 줄로 접혀
   버튼 높이가 들쭉날쭉해진다(육안 검수 2026-08-26). 좁으면 줄째 내려가면 된다. */
.btn{white-space:nowrap;display:inline-flex;align-items:center;justify-content:center;height:36px;padding:0 var(--s4);border-radius:var(--radius-md);
  font-size:13px;font-weight:500;font-family:inherit;cursor:pointer;border:1px solid transparent;
  transition:background .15s var(--ease),border-color .15s var(--ease),color .15s var(--ease)}
.btn:active{transform:translateY(1px)}
.btn-primary{background:var(--brand);color:var(--on-brand)} .btn-primary:hover{background:var(--brand-deep)}
.btn-secondary{background:var(--surface-card);color:var(--text-primary);border-color:var(--border-subtle)}
.btn-secondary:hover{border-color:var(--brand);color:var(--brand)}
.btn-tall{height:40px}
/* 상단바용 — 56px 바 안에서 위아래가 답답하지 않은 높이 */
.btn-sm{height:34px;font-weight:600}
/* 복사 완료 피드백 — 텍스트만 바뀌므로 레이아웃이 흔들리지 않는다 */
.btn.is-done{background:var(--state-up);border-color:var(--state-up);color:var(--on-brand)}

.input{height:40px;padding:0 var(--s3);border-radius:var(--radius-md);border:1px solid var(--border-subtle);
  outline:none;background:var(--surface-card);color:var(--text-primary);font-size:14px;font-family:inherit;width:100%;max-width:22em}
.input:focus{border-color:var(--brand);box-shadow:0 0 0 3px var(--focus-ring)}
.input-mono{font-family:var(--font-mono)}
/* 파일 입력은 .input 의 height:40px + padding:0 을 그대로 쓰면 네이티브 '파일 선택' 버튼이
   세로 중앙에 안 잡히고 박스 위로 삐져나온다(2026-08-28 육안 검수). 버튼을 직접 그려서
   높이를 박스에 맞춘다 — 좌측 붙박이 버튼 + 우측 파일명. */
input[type="file"].input{display:flex;align-items:center;padding:0;font-size:13px;
  color:var(--text-secondary);cursor:pointer;overflow:hidden}
input[type="file"].input::file-selector-button{height:38px;margin:0 var(--s3) 0 0;padding:0 var(--s4);
  border:0;border-right:1px solid var(--border-subtle);background:var(--bg-subtle);
  color:var(--text-primary);font:inherit;font-size:13px;font-weight:600;cursor:pointer}
input[type="file"].input::file-selector-button:hover{background:var(--surface-elevated)}

/* 주소는 잘리면 안 된다 — 고객이 그대로 붙여넣는 값이라 조용한 잘림이 곧 오류다.
   가로 스크롤 대신 줄바꿈으로 전체를 보인다(브리프 §6.3). */
.addr{font-family:var(--font-mono);font-size:13px;color:var(--text-primary);background:var(--bg-subtle);
  padding:var(--s2) 10px;border-radius:var(--s2);display:block;margin-top:var(--s2);
  white-space:pre-wrap;word-break:break-all;overflow-wrap:anywhere}
pre{background:var(--bg-subtle);border:1px solid var(--border-subtle);border-radius:10px;padding:14px;overflow-x:auto;margin:var(--s2) 0}
pre code{font-family:var(--font-mono);font-size:13px}
.row{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap}
/* 표 셀 안의 인라인 폼(관리 목록의 등급 변경)은 예외다 — .input 의 width:100% 가 좁은
   셀을 통째로 먹어 '변경' 버튼이 다음 줄로 밀린다(2026-08-23 육안 검수에서 확인).
   덮을 때는 폭 관련 속성을 한꺼번에 명시한다: 일부만 덮으면 나머지가 새어 들어오고,
   그 누수는 명시도를 손으로 따져보기 전엔 안 보인다. 적용 범위는 table.tk 안의 폼뿐이라
   발급 폼(.card 안)·로그인 폼은 그대로 100% 를 유지한다. */
table.tk td form.row .input{width:auto;max-width:none;min-width:0;flex:0 1 auto}

/* ── 좌측 사이드바 (둘러보기·관리) ── */
/* 목록이 긴 화면에만 단다. 읽는 화면(홈·상세·마이페이지)에 달면 본문만 좁아진다. */
.side-shell{display:grid;grid-template-columns:212px minmax(0,1fr);gap:var(--s8);align-items:start}
.side{position:sticky;top:84px;padding-top:var(--s8)}
.side-main{min-width:0}
.side-group + .side-group{margin-top:var(--s6)}
.side-h{font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:var(--text-secondary);padding:0 10px;margin-bottom:6px}
.side-item{display:block;padding:7px 10px;border-radius:9px;font-size:13.5px;
  color:var(--text-secondary);line-height:1.5}
.side-item:hover{background:var(--bg-subtle);color:var(--text-primary);opacity:1}
/* 지금 보고 있는 곳 — 어디에 있는지 모르면 메뉴가 소용없다. */
.side-item.is-on{background:var(--tint);color:var(--brand);font-weight:600}

/* ── 관리 서브 내비 ── */
/* 고객사·키와 카탈로그는 동등한 기능이다 — 한쪽을 다른 쪽 하위로 두지 않는다. */
.admin-nav{display:flex;gap:6px;flex-wrap:wrap;padding-top:var(--s8);margin-bottom:var(--s2)}
.admin-tab{padding:7px 14px;border-radius:999px;font-size:13px;font-weight:600;
  color:var(--text-secondary);background:var(--bg-subtle)}
.admin-tab:hover{color:var(--text-primary);opacity:1}
.admin-tab.is-on{background:var(--brand);color:var(--on-brand)}
/* 서브 내비가 이미 위치를 말해 준다 — 제목 위 여백을 두 번 주지 않는다. */
.admin-nav + .page-head{padding-top:var(--s4)}

/* 관리 화면 필터 — 카탈로그가 늘어나면 목록만으로는 못 찾는다. */
.ct-filter{margin-bottom:var(--s4);gap:8px}
.ct-filter .input{max-width:260px}
.ct-count{font-size:12px;color:var(--text-secondary);margin-left:6px}
/* 행 액션은 글자로 말한다 — 아이콘만 있으면 무엇을 하는 버튼인지 눌러 봐야 안다. */
/* 세 버튼이 한 줄을 유지해야 한다 — 칸이 좁아지면 겹쳐 보인다(육안 검수 2026-08-24).
   nowrap 으로 고정하고, 열 자체가 내용만큼 폭을 갖게 한다. */
/* 주의: width:1%(=내용 폭으로 축소)는 flex 컨테이너의 내용 폭을 계산하지 못한다 —
   셀이 26px 로 찌그러지고 버튼 세 개가 겹쳐 보였다(육안 검수 2026-08-24).
   최소 폭을 직접 준다. */
/* 열을 둘로 줄였다 — 한 행에 컨트롤이 일곱인데 열까지 셋이면 표의 자동 폭 계산과
   flex 가 계속 충돌해 셀이 찌그러진다(육안 검수에서 세 번 어긋났다). 설정과 액션을
   한 칸에 넣고 그 안에서만 flex 로 배치한다. */
.ct-actions{display:flex;align-items:center;gap:10px;flex-wrap:nowrap;justify-content:flex-end}
.ct-actions form{display:flex;align-items:center;gap:10px;flex:none}
.ct-sep-v{width:1px;height:22px;background:var(--border-subtle);flex:none}
.ct-th-act{text-align:right}
/* 한 행에 컨트롤이 일곱이다(보임·범위·추천·저장·위·아래·삭제) — 좁은 화면에서는
   줄바꿈으로 뭉개지 말고 표를 가로로 밀어 준다. 뭉개진 표는 못 읽지만 스크롤은 읽힌다. */
.ct-scroll{overflow-x:auto}
.ct-scroll .tk{min-width:900px}
.btn-mini{height:28px;padding:0 10px;font-size:12px;width:auto;border-radius:8px}
/* ── 아이콘 버튼 · ⋯ 메뉴 · 키 가리기 (2026-08-26 관리 화면 개편) ── */
/* 글자 버튼이 한 줄에 다섯 개면 어느 것이 위험한지 안 보인다 — 자주 쓰는 것만 모양으로
   내놓고 나머지는 ⋯ 뒤로. 아이콘만 남기되 aria-label·title 로 말은 남긴다. */
.ibtn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;flex:none;
  border:1px solid transparent;border-radius:8px;background:transparent;color:var(--text-secondary);
  cursor:pointer;padding:0;transition:background .15s var(--ease),color .15s var(--ease)}
.ibtn svg{width:17px;height:17px}
.ibtn:hover{background:var(--bg-subtle);color:var(--text-primary);opacity:1}
.ibtn-sm{width:26px;height:26px}
.ibtn-sm svg{width:15px;height:15px}
/* 되돌릴 수 없는 동작은 색으로도 구별된다 — 모양만으로는 옆 버튼과 같은 무게로 읽힌다. */
.ibtn-danger:hover{background:var(--state-down);color:var(--bg-page);border-color:var(--state-down)}
/* 눈 버튼이 켜지면 "지금 보이는 중"이 버튼에도 남는다. */
.ibtn.is-on{color:var(--brand)}

/* ⋯ 메뉴 — <details> 라 자바스크립트 없이 열린다(계정 드롭다운과 같은 방식). */
.menu{position:relative;flex:none}
.menu > summary{list-style:none;cursor:pointer}
.menu > summary::-webkit-details-marker{display:none}
.menu[open] > summary{background:var(--bg-subtle);color:var(--text-primary)}
.menu-pop{position:absolute;right:0;top:34px;z-index:20;min-width:150px;padding:6px;
  border:1px solid var(--border-subtle);border-radius:12px;background:var(--surface-card);
  box-shadow:var(--shadow-card-hover)}
.menu-item{display:block;width:100%;text-align:left;padding:8px 10px;border:0;border-radius:8px;
  background:transparent;color:var(--text-primary);font-size:13px;font-family:inherit;cursor:pointer}
.menu-item:hover{background:var(--bg-subtle)}
.menu-item-danger{color:var(--state-down)}

/* ── 끌어서 순서 바꾸기 (레퍼런스: AE 「분석 주체 정렬」 모달) ── */
.ord-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px;
  max-height:min(52vh,420px);overflow-y:auto}
.ord-item{display:flex;align-items:center;gap:10px;padding:10px 12px;cursor:grab;
  border:1px solid var(--border-subtle);border-radius:12px;background:var(--surface-card)}
.ord-item:hover{border-color:var(--brand)}
/* 끌고 있는 줄은 옅게 — 지금 어느 것을 들고 있는지 보여야 놓을 자리를 고른다. */
.ord-item.is-drag{opacity:.4;cursor:grabbing}
.ord-grip{width:16px;height:16px;flex:none;color:var(--text-secondary)}
.ord-n{flex:none;min-width:20px;font-family:var(--font-mono);font-size:12px;color:var(--text-secondary);
  font-variant-numeric:tabular-nums}
.ord-t{font-size:14px;font-weight:600;color:var(--text-primary)}
.ord-s{font-family:var(--font-mono);font-size:11px;color:var(--text-secondary)}
/* 분류 화면은 같은 줄 안에서 이름을 바로 고친다 — 입력이 줄을 밀지 않게 폭을 정한다. */
.cat-row{display:flex;align-items:center;gap:10px;flex:1;min-width:0}
.cat-name{max-width:16em;height:32px}
.cat-used{margin-left:auto;font-size:12px;color:var(--text-secondary);flex:none}

/* 키 칸 — 점과 눈 버튼이 한 줄에. 펼치면 키가 길어지므로 줄바꿈을 허용한다. */
.key-cell{display:inline-flex;align-items:center;gap:6px;max-width:34ch}
.key-cell code{font-family:var(--font-mono);font-size:12px;word-break:break-all}
.btn-danger:hover{border-color:var(--state-down,#d92d20);color:var(--state-down,#d92d20)}
/* 추가 모달은 폼이 길다 — 로그인 모달보다 넓게, 넘치면 안에서 스크롤한다. */
.dlg-wide{max-width:min(560px,calc(100vw - 32px))}
.dlg-wide .dlg-body{max-height:calc(100vh - 96px);overflow-y:auto}

/* ── 항목 추가 폼 ── */
.ct-field{display:block;margin-bottom:var(--s4)}
.ct-label{display:block;font-size:13px;font-weight:600;color:var(--text-primary);margin-bottom:6px}
.ct-field .input{max-width:520px}
.ct-hint{display:block;margin-top:5px;font-size:12px;color:var(--text-secondary)}
.ct-area{height:auto;padding:10px var(--s3);line-height:1.6;resize:vertical}
.ct-del{white-space:nowrap}
/* 삭제는 되돌릴 수 없다 — 눈에 띄되 먼저 눌리지는 않게 옅은 상태에서 시작한다. */
.ct-del .btn-ghost{color:var(--text-secondary)}
.ct-del .btn-ghost:hover{border-color:var(--state-down,#d92d20);color:var(--state-down,#d92d20)}
.toolbar .push{margin-left:auto}

/* ── 카탈로그 관리 표 ── */
.ct-name{font-weight:600;color:var(--text-primary)}
.ct-slug{font-family:var(--font-mono);font-size:12px;color:var(--text-secondary)}
/* .row 는 flex-wrap:wrap 이다 — 셀 폭을 내용에 맞추면(width:1%) 그 wrap 이 폼을
   세로로 쌓아버린다. 이 폼만은 한 줄을 유지한다. */
.ct-form{gap:10px;flex-wrap:nowrap}
/* 체크박스와 글자가 따로 놀지 않게 묶는다 — 라벨을 눌러도 켜져야 한다. */
.ct-check{display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--text-secondary);
  white-space:nowrap;cursor:pointer}
.ct-check input{accent-color:var(--brand);width:15px;height:15px;cursor:pointer}
.ct-move{white-space:nowrap}
.ct-move form{display:inline-flex}
.btn-ghost{border:1px solid var(--border-subtle);background:transparent;color:var(--text-secondary);
  border-radius:10px;width:32px;height:32px;padding:0;display:inline-flex;align-items:center;
  justify-content:center;cursor:pointer;font-size:14px}
.btn-ghost:hover{border-color:var(--brand);color:var(--brand)}
/* 변경 내용은 길어질 수 있다 — 줄바꿈을 허용해 표를 밀지 않게 한다. */
.ct-diff{font-size:12px;color:var(--text-secondary);font-family:var(--font-mono);
  word-break:break-all;max-width:32em}
.hairline{height:1px;background:var(--border-subtle);border:0;margin:var(--s6) 0}
.notice{font-size:13px;color:var(--text-secondary);border-left:2px solid var(--border-subtle);padding-left:10px;margin:0 0 var(--s4)}

table.tk{width:100%;border-collapse:collapse;font-size:14px}
table.tk th{font-size:12px;font-weight:500;color:var(--text-secondary);text-align:left;
  padding:var(--s2) 10px;border-bottom:1px solid var(--border-subtle)}
table.tk td{padding:10px;border-bottom:1px solid var(--border-subtle);vertical-align:middle}
/* 숫자 열은 머리글과 값이 같은 축에 서야 한다. 마크업은 이미 <th class="num"> 으로
   의도를 밝혔는데 여기 td.num 만 있어서 머리글은 table.tk th 의 왼쪽 정렬을 그대로
   받았다 — 값은 오른쪽 끝, 머리글은 한참 왼쪽(사용자 지적 2026-08-26).
   th 와 td 의 좌우 패딩이 10px 로 같으므로 정렬만 맞추면 축이 정확히 겹친다. */
table.tk th.num,table.tk td.num{text-align:right;font-variant-numeric:tabular-nums}
table.tk tbody tr:hover{background:var(--bg-subtle)}
table.tk code{font-family:var(--font-mono);font-size:12px;word-break:break-all}

/* ══ 카탈로그 셸 (레퍼런스: playmcp.kakao.com — 사용자 지정) ═══════════════
   상단 좌측 로고 + 내비 · 우측 계정 / 본문은 1072 폭 가운데 한 칼럼.
   치수는 레퍼런스에서 실측해 옮겼다: 본문 1072, 카드 526×2 + gap 20, radius 20,
   패딩 25, 검색 pill 280×38(r19), 카드 제목 18/700, 설명 3줄 말줄임.
   색은 우리 DS 그대로다(라이트 기본 + 브랜드 블루) — 레퍼런스는 다크 단일이지만
   가져오는 건 구성이지 팔레트가 아니다(사용자 확정). */
.top{position:sticky;top:0;z-index:20;background:var(--bg-page);border-bottom:1px solid var(--border-subtle)}
.top-in{max-width:1400px;margin:0 auto;padding:0 20px;height:64px;display:flex;align-items:center;gap:var(--s8)}
.nav-logo{display:inline-flex;align-items:center;flex:none}
.nav-logo img{height:22px;width:auto}
.top-name{font-size:14px;font-weight:700;color:var(--text-primary);flex:none;letter-spacing:-.01em}
.top-name:hover{color:var(--brand);opacity:1}
.top-nav{display:flex;align-items:center;gap:var(--s6);font-size:14px;font-weight:500}
.top-nav a{color:var(--text-secondary)}
.top-nav a:hover{color:var(--text-primary);opacity:1}
.top-nav a.is-active{color:var(--text-primary);font-weight:600}
.top-right{margin-left:auto;display:flex;align-items:center;gap:var(--s3);font-size:13px;flex:none}
.top-right .muted-n{max-width:14em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* 계정 드롭다운 — 등급·로그아웃을 상단바에 늘어놓지 않고 하나로 접는다.
   <details> 라 자바스크립트가 없어도 열린다(바깥 클릭으로 닫히지는 않는다 — 그 정도는 감수한다). */
.acct{position:relative}
.acct-btn{list-style:none;display:inline-flex;align-items:center;gap:var(--s2);height:34px;
  padding:0 10px 0 6px;border-radius:var(--radius-pill);border:1px solid var(--border-subtle);
  background:var(--surface-card);cursor:pointer;transition:border-color .15s var(--ease)}
.acct-btn::-webkit-details-marker{display:none}
.acct-btn:hover{border-color:var(--brand)}
.acct-avatar{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;flex:none;
  border-radius:50%;background:var(--tint);color:var(--brand);font-size:11px;font-weight:700}
.acct-caret{width:12px;height:12px;flex:none;color:var(--text-secondary);transition:transform .15s var(--ease)}
.acct[open] .acct-caret{transform:rotate(180deg)}
.acct-menu{position:absolute;right:0;top:calc(100% + 8px);min-width:220px;z-index:30;padding:var(--s2);
  background:var(--surface-card);border:1px solid var(--border-subtle);border-radius:14px;
  box-shadow:var(--shadow-card-hover)}
.acct-row{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  padding:var(--s2) 10px;font-size:13px;color:var(--text-secondary)}
.acct-sep{height:1px;background:var(--border-subtle);margin:6px 0}
/* 머리 — 이름·소속·등급. 메뉴 항목과 섞이지 않게 배경으로 가른다. */
.acct-head{padding:10px 10px 12px}
.acct-who{font-size:14px;font-weight:700;color:var(--text-primary)}
.acct-sub{margin-top:2px;font-size:12px;color:var(--text-secondary)}
/* 로그아웃은 결과가 다른 항목이다 — 색으로도 구분한다(글자만으로는 눈이 안 멈춘다). */
.acct-out{color:var(--state-down,#d92d20)}
.acct-out:hover{background:var(--bg-subtle);color:var(--state-down,#d92d20);opacity:1}
.acct-item{display:block;padding:9px 10px;border-radius:var(--s2);font-size:13px;color:var(--text-primary)}
.acct-item:hover{background:var(--bg-subtle);opacity:1}

/* 본문 폭은 상단바(.top-in)와 같아야 한다 — 다르면 로고와 제목의 좌측이 어긋나 화면이
   기준선을 두 개 갖는다. 1112 → 1400 확대(사용자 결정 2026-08-23): 넓은 화면에서 좌우
   여백이 과해 "너무 중앙정렬"로 읽혔다. */
.wrap{max-width:1400px;margin:0 auto;padding:0 20px 60px}
/* 상세·폼처럼 한 덩어리인 화면은 더 좁게 — 전체 폭을 쓰면 문장이 가로로 퍼져 읽기 나쁘다.
   단 컨테이너가 아니라 **내용**을 좁힌다: 컨테이너를 좁히면(옛 max-width:760px) 넓은
   화면에서 본문 전체가 한가운데로 떠 상단바 로고와 시작점이 어긋났다. 이제 왼쪽부터 흐른다. */
.wrap-narrow > *{max-width:960px}
/* 로그인·오류처럼 한 장짜리 화면은 가운데가 맞다 — 읽을 것이 그것뿐이라 좌정렬하면
   넓은 화면에서 왼쪽 구석에 매달린 것처럼 보인다. */
/* 로그인·오류는 화면에 그것 하나뿐이다 — 위에 붙여 두면 아래가 통째로 비어 보인다.
   세로로도 가운데 둔다(헤더 64 + .wrap 하단 여백 60 을 뺀 높이 기준). */
/* ── 로그인 모달 ── */
/* <dialog> 는 top-layer 라 부모의 overflow·z-index 에 갇히지 않는다. 기본 여백·테두리를
   지우고 카드처럼 보이게만 한다. */
.dlg{border:0;padding:0;background:transparent;max-width:min(460px,calc(100vw - 32px));width:100%}
.dlg::backdrop{background:rgba(15,18,25,.55)}
/* 그림자를 얹지 않는다 — DS 규칙(투명도 5% 이하)에 맞지 않고, backdrop 이 이미
   뒤 화면을 눌러 카드를 분리해 준다. */
.dlg-body{position:relative;border:1px solid var(--border-subtle);border-radius:20px;
  background:var(--surface-card);padding:var(--s6)}
.dlg-x{position:absolute;top:10px;right:10px;z-index:1}
.dlg-x button{border:0;background:transparent;color:var(--text-secondary);font-size:15px;
  width:32px;height:32px;border-radius:10px;cursor:pointer;line-height:1}
.dlg-x button:hover{background:var(--bg-subtle);color:var(--text-primary)}

.wrap-center{max-width:760px;margin:0 auto;min-height:calc(100vh - 124px);
  display:flex;flex-direction:column;justify-content:center}

/* ── 히어로: 가운데 정렬 큰 문장 하나 ── */
.hero{text-align:center;padding:var(--s12) 0 var(--s8)}
.hero-eyebrow{font-size:13px;font-weight:600;color:var(--brand);margin:0 0 var(--s4)}
.hero-title{font-size:40px;line-height:1.35;font-weight:700;letter-spacing:-.02em;margin:0;color:var(--text-primary)}
.hero-sub{font-size:15px;line-height:1.7;color:var(--text-secondary);margin:var(--s4) auto 0;max-width:40em}
.hero-cta{display:flex;justify-content:center;gap:10px;margin-top:var(--s6);flex-wrap:wrap}

/* ── 시작 3단계: 카드가 아니라 얇은 3열 — 히어로 아래에서 무게를 다투면 안 된다 ── */
.steps{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s6);
  padding:var(--s6) 0 var(--s12);border-bottom:1px solid var(--border-subtle);margin-bottom:var(--s12)}
.step-top{display:flex;align-items:center;gap:9px;margin-bottom:6px}
.step-num{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;flex:none;
  border-radius:50%;background:var(--brand);color:var(--on-brand);font-size:11px;font-weight:700}
.step-t{font-size:14px;font-weight:700;color:var(--text-primary)}
.step-d{font-size:13px;line-height:1.65;color:var(--text-secondary)}

/* ── 도구 모음줄: 좌 종류 탭 · 우 검색 ── */
.toolbar{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;margin-bottom:var(--s4)}
.tabs{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap}
.tab{display:inline-flex;align-items:center;gap:6px;height:34px;padding:0 14px;border-radius:var(--radius-pill);
  font-size:13px;color:var(--text-secondary);background:var(--bg-subtle);
  transition:background .15s var(--ease),color .15s var(--ease)}
.tab:hover{color:var(--text-primary);opacity:1}
.tab.is-active{background:var(--text-primary);color:var(--bg-page);font-weight:600}
.search{display:flex;align-items:center;gap:var(--s2);width:280px;max-width:100%;height:38px;
  padding:0 14px;border-radius:19px;background:var(--bg-subtle);border:1px solid transparent;
  transition:border-color .15s var(--ease),box-shadow .15s var(--ease)}
.search-push{margin-left:auto}
.search:focus-within{border-color:var(--brand);box-shadow:0 0 0 3px var(--focus-ring)}
.search svg{width:15px;height:15px;flex:none;color:var(--text-secondary)}
.search input{flex:1;min-width:0;border:0;outline:0;background:transparent;
  font-size:13px;font-family:inherit;color:var(--text-primary)}

/* ── 카드 격자 (2열) ── */
/* 2열 고정이었다 — 폭을 1400 으로 넓히면 카드가 그만큼 거대해져 한 장에 담긴 정보량과
   크기가 어긋난다. 카드 최소폭을 정하고 남는 만큼 열을 채운다(1400 에서 4열). */
.cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:20px}
.mcard{display:flex;flex-direction:column;min-height:196px;padding:22px;border-radius:20px;
  background:var(--surface-card);border:1px solid var(--border-subtle);
  transition:border-color .15s var(--ease),box-shadow .15s var(--ease)}
.mcard:hover{border-color:var(--brand);box-shadow:var(--shadow-card-hover)}
/* 머리는 [아이콘][이름+배지 / 슬러그] — 레퍼런스(lobehub·skillsmp)가 공통으로 쓰는 배치다.
   아이콘을 왼쪽 고정 칸에 두면 목록에서 시선이 세로로 정렬돼 훑기가 쉬워진다. */
.mcard-head{display:flex;align-items:flex-start;gap:14px}
.mcard-ico{flex:none;width:44px;height:44px;border-radius:13px;background:var(--tint);
  display:inline-flex;align-items:center;justify-content:center;color:var(--brand)}
.mcard-ico svg{width:22px;height:22px}
.mcard-id{flex:1;min-width:0;display:block}
/* 배지가 이름 뒤에 붙되 이름이 길면 배지부터 다음 줄로 내려간다. */
.mcard-line{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.mcard-name{font-size:17px;font-weight:700;letter-spacing:-.01em;color:var(--text-primary)}
.mcard-name:hover{color:var(--brand);opacity:1}
.mcard-slug{display:block;margin-top:3px;font-family:var(--font-mono);font-size:12px;color:var(--text-secondary)}
.badge-sm{font-size:11px;padding:1px 7px}
/* 상태 톤 — MCP 모니터링(2026-08-26, 포털에서 이관).
   라이트/다크 값은 :root 변수가 이미 쌍으로 갖고 있으므로 규칙은 한 벌이면 된다.
   글자색(tone-*)과 배지(badge-*)를 나눈 이유: 표 안에서는 글자만, 요약에서는 면을 칠한다. */
.tone-up{color:var(--state-up)} .tone-warn{color:var(--state-warning)}
.tone-down{color:var(--state-down)} .tone-info{color:var(--state-info)}
.tone-muted{color:var(--text-secondary)}
.badge-up{background:color-mix(in srgb,var(--state-up) 12%,transparent);color:var(--state-up)}
.badge-warn{background:color-mix(in srgb,var(--state-warning) 12%,transparent);color:var(--state-warning)}
.badge-down{background:color-mix(in srgb,var(--state-down) 12%,transparent);color:var(--state-down)}
.badge-info{background:color-mix(in srgb,var(--state-info) 12%,transparent);color:var(--state-info)}
/* 심각도 마커 — 색 **과** 형태로 이중 부호화한다. 색만 쓰면 색각 이상 사용자에게
   세 등급이 한 덩어리로 보인다. filled=채움 원, ring=테두리 원, bar=가는 막대. */
.sev{display:inline-block;flex:0 0 auto;margin-top:6px}
.sev-filled{width:8px;height:8px;border-radius:50%;background:currentColor}
.sev-ring{width:8px;height:8px;border-radius:50%;border:1.5px solid currentColor}
.sev-bar{width:10px;height:2px;background:currentColor;margin-top:9px}

/* ── MCP 모니터링 (2026-08-26, 포털에서 이관) ─────────────────────────────
   포털은 React + 차트 라이브러리였다. 여기는 외부 리소스 요청 0 이 원칙이라
   차트를 인라인 SVG 로 그린다 — 색은 전부 시맨틱 변수로만 쓴다. */
.fmono{font-family:var(--font-mono);font-size:12.5px;color:var(--text-secondary)}
.head-line{font-size:24px;font-weight:700;letter-spacing:-.01em}
/* 일괄 저장 바 — 표 바로 아래 붙는다. 화면 밖으로 나가면 무엇을 저장하는지 안 보인다 */
/* 변경 이력 — 요약이 기본, 전문은 펼쳐서. 프롬프트 수천 자가 표 한 줄을 덮으면
   그 아래 이력이 아예 안 보인다 */
.dif > summary{cursor:pointer;list-style:none;font-size:12.5px}
.dif > summary::-webkit-details-marker{display:none}
.dif > summary::before{content:'▸ ';color:var(--text-secondary)}
.dif[open] > summary::before{content:'▾ '}
.dif-k{font-family:var(--font-mono);color:var(--text-primary)}
.dif-b{margin-top:var(--s2);font-size:12px;color:var(--text-secondary);
  line-height:1.6;overflow-wrap:anywhere;max-height:16em;overflow-y:auto}
/* 계정 목록 — 사람이 먼저 보이고 이메일·제공자는 그 아래 작게 */
.ac-n{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap;font-size:14px;color:var(--text-primary);font-weight:600}
.ac-e{margin-top:2px;font-family:var(--font-mono);font-size:11.5px;color:var(--text-secondary)}
.ac-act{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap}
.ac-move{display:flex;gap:6px;align-items:center}
/* 열이 늘어 폭이 귀하다(2026-08-27) — 셀렉트가 길면 관리 열이 카드 밖으로 밀린다 */
.ac-move .input{width:auto;max-width:132px;padding:5px 8px;font-size:12.5px;
  text-overflow:ellipsis;white-space:nowrap;overflow:hidden}
/* 계정 코드 — 행의 안정된 주소. 링크처럼 파란 모노로 눈에 걸리게(레퍼런스 UI 관례) */
.ac-code{font-size:12px;color:var(--text-brand);white-space:nowrap}
/* 날짜는 한 줄 — 열이 늘며 "2026-08-27 10:58" 이 두 줄로 꺾였다(2026-08-27 렌더 실측).
   공용 .tk 를 건드리지 않고 이 화면의 시간 셀에만 건다. */
.ac-t{white-space:nowrap}
.ac-person{display:flex;gap:10px;align-items:center}
/* 아바타 — 이니셜 원. 색은 id 로 정해져(av-0..5) 같은 사람이 항상 같은 색이다 */
.ac-avatar{flex:none;width:32px;height:32px;border-radius:50%;display:inline-flex;
  align-items:center;justify-content:center;font-size:13px;font-weight:700;color:#fff}
.av-0{background:#2563eb}.av-1{background:#7c3aed}.av-2{background:#0d9488}
.av-3{background:#dc7609}.av-4{background:#db2777}.av-5{background:#475569}
/* 역할 — 관리자/일반이 색으로도 갈린다(색+텍스트 이중 부호). 셀렉트는 고르면 바로 제출 */
.role-select{border:1px solid var(--border-subtle);border-radius:8px;padding:4px 8px;
  font-size:12.5px;font-weight:600;background:var(--surface-card);cursor:pointer}
.role-select.role-admin{color:var(--state-down);border-color:color-mix(in srgb,var(--state-down) 40%,transparent)}
.role-select.role-user{color:var(--state-up);border-color:color-mix(in srgb,var(--state-up) 40%,transparent)}
.role-pill{font-size:12.5px;font-weight:600;color:var(--text-secondary)}
.role-pill.role-user{color:var(--text-secondary)}
/* 상태 배지 — 활성은 초록 틴트(모니터링의 정상 표기와 같은 계열) */
.badge-ok{background:color-mix(in srgb,var(--state-up) 14%,transparent);color:var(--state-up)}
/* 해지된 줄은 옅게 — 지우지 않고 남기되 눈에 먼저 들어오지 않게 */
tr.is-off{opacity:.55}
.ct-save{display:flex;gap:var(--s3);align-items:center;flex-wrap:wrap;margin-top:var(--s3)}
/* 쪽 넘기기 — 목록이 아래로만 길어지면 찾을 수 없다 */
.pager{display:flex;gap:var(--s3);align-items:center;justify-content:center;margin-top:var(--s4)}
/* 기간 선택기 — 팝오버 안에 이름 붙은 기간(좌)과 직접 지정(우). TE 기간 선택기 참고 */
.rg{position:relative}
.rg-btn{cursor:pointer;list-style:none;display:inline-flex;gap:var(--s2);align-items:center;
  padding:7px 13px;border:1px solid var(--border-subtle);border-radius:var(--radius-pill);
  font-size:13px;color:var(--text-primary);background:var(--surface-card);white-space:nowrap}
.rg-btn::-webkit-details-marker{display:none}
.rg-btn:hover{border-color:var(--brand)}
.rg[open] .rg-btn{border-color:var(--brand);color:var(--brand)}
.rg-cal{color:var(--text-secondary);font-size:11px}
/* 오른쪽 끝에 붙여 띄운다. 화면 밖으로 나가지 않게 최대 폭을 잡는다 */
.rg-pop{position:absolute;right:0;top:calc(100% + 6px);z-index:30;display:flex;
  background:var(--surface-card);border:1px solid var(--border-subtle);
  border-radius:var(--radius-md);box-shadow:var(--shadow-card-hover);
  max-width:min(440px,calc(100vw - 32px))}
.rg-side{display:flex;flex-direction:column;gap:2px;padding:var(--s3);
  border-right:1px solid var(--border-subtle);min-width:132px}
.rg-h{font-size:11px;font-weight:700;letter-spacing:.06em;color:var(--text-secondary);
  text-transform:uppercase;margin-bottom:var(--s1)}
.rg-item{padding:6px 9px;border-radius:8px;font-size:13px;color:var(--text-primary);
  text-decoration:none;white-space:nowrap}
.rg-item:hover{background:var(--bg-subtle)}
.rg-item.is-on{background:var(--tint);color:var(--brand);font-weight:600}
.rg-main{display:flex;flex-direction:column;gap:var(--s2);padding:var(--s3);min-width:180px}
.rg-f{display:flex;flex-direction:column;gap:4px;font-size:12px;color:var(--text-secondary)}
.rg-f .input{width:100%;padding:6px 9px;font-size:13px}
.rg-act{margin-top:auto;display:flex;justify-content:flex-end}
@media (max-width:560px){ .rg-pop{flex-direction:column} .rg-side{border-right:0;border-bottom:1px solid var(--border-subtle)} }

.chart-w{display:flex;flex-direction:column;gap:var(--s2)}
.chart-sum{display:flex;gap:var(--s4);align-items:center;flex-wrap:wrap}
.chart-dot{fill:var(--brand);opacity:0;pointer-events:none;transition:opacity .12s var(--ease)}
.hit:hover .chart-dot{opacity:1}
.hit rect{cursor:crosshair}
.range-f .input{width:auto;padding:6px 9px;font-size:13px}

/* 차트 — viewBox 로 그리고 CSS 로 늘린다(반응형). 높이를 고정하지 않는다. */
.chart{width:100%;height:auto;display:block}
.chart-line{fill:none;stroke:var(--brand);stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
.chart-area{fill:var(--brand);opacity:.08;stroke:none}
.chart-bar{fill:var(--brand)}
.chart-axis{stroke:var(--border-subtle);stroke-width:1}
.chart-grid{stroke:var(--border-subtle);stroke-width:1;stroke-dasharray:3 4}
.chart-t{fill:var(--text-secondary);font-size:11px;font-family:var(--font-mono)}
.chart-t-end{text-anchor:end}
.chart-t-mid{text-anchor:middle}
/* 최고점 값은 눈에 보이게 — 마우스를 못 대는 상황(캡처·인쇄)에도 읽혀야 한다 */
.chart-t-on{fill:var(--text-primary);font-weight:700;font-size:12px}
.chart-peak{fill:var(--brand)}

/* 순위 막대 — 색상환을 돌지 않고 같은 브랜드색의 투명도만 낮춘다(rankBarAlpha). */
.ranks{display:flex;flex-direction:column;gap:var(--s2)}
.rank{display:grid;grid-template-columns:minmax(0,150px) 1fr auto;gap:var(--s3);align-items:center}
.rank-l{font-size:13px;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rank-track{background:var(--bg-subtle);border-radius:var(--radius-pill);height:10px;overflow:hidden}
.rank-fill{height:100%;background:var(--brand);border-radius:var(--radius-pill)}
.rank-n{font-family:var(--font-mono);font-size:12px;color:var(--text-secondary);
  font-variant-numeric:tabular-nums;min-width:52px;text-align:right}

/* 문제 목록 — 마커는 색과 형태 둘 다로 등급을 말한다(.sev-*). */
.probs{display:flex;flex-direction:column;gap:var(--s4)}
.prob{display:flex;gap:var(--s3);align-items:flex-start}
.prob-b{min-width:0;flex:1}
.prob-h{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap}
.prob-m{font-family:var(--font-mono);font-size:12.5px;color:var(--text-primary)}
.prob-d{margin-top:var(--s1);font-size:13.5px;color:var(--text-secondary);line-height:1.55}
.prob-t{margin-top:var(--s1);font-size:11.5px;color:var(--text-secondary);opacity:.8}

/* 오류 그룹 — 문구가 길어 줄바꿈을 허용하되 가로 스크롤은 막는다. */
/* 개요 카드 — 숫자만 보여주고 갈 곳이 없으면 다음 질문에서 막힌다. 카드 전체가 링크다. */
.ovs{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--s3);margin-bottom:var(--s6)}
.ov{display:block;padding:var(--s4);border:1px solid var(--border-subtle);border-radius:var(--radius-lg);
  background:var(--surface-card);text-decoration:none;transition:border-color .15s var(--ease)}
.ov:hover{border-color:var(--brand)}
.ov-l{font-size:12.5px;color:var(--text-secondary)}
.ov-v{margin-top:var(--s1);font-family:var(--font-mono);font-size:24px;font-weight:700;
  color:var(--text-primary);font-variant-numeric:tabular-nums}
.ov-n{margin-top:2px;font-size:11.5px;color:var(--text-secondary)}
.err-sum{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap;margin-bottom:var(--s4);font-size:13.5px}
.err-g + .err-g{margin-top:var(--s3)}
.err-h{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap}
.err-n{font-family:var(--font-mono);font-size:13px;font-weight:600}
.err-t{margin-top:var(--s2);font-size:13.5px;line-height:1.55;color:var(--text-primary);
  overflow-wrap:anywhere}
.err-m{margin-top:var(--s1);font-size:11.5px;color:var(--text-secondary)}
.err-d{margin-top:var(--s3)}
.err-d summary{cursor:pointer;font-size:12.5px;color:var(--text-secondary)}
.err-d > table{margin-top:var(--s2)}
/* 설명은 2줄에서 자른다 — 머리가 두 줄(이름+슬러그)이 되었으니 3줄이면 카드가 세로로 늘어진다. */
/* 최대 2줄로 자르되 **자리도 2줄을 잡는다**. 안 그러면 설명이 한 줄인 카드만 아래가
   벌어져 격자의 세로 리듬이 카드마다 달라진다(2026-08-30 검토). 푸터는 이미 하단 고정이라
   그 차이가 설명과 푸터 사이 공백으로 그대로 드러났다. */
.mcard-desc{margin:14px 0 0;font-size:13.5px;line-height:1.65;color:var(--text-secondary);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  min-height:calc(1.65em * 2)}
/* 하단은 구분선 위에 올린다 — 본문과 메타가 붙어 있으면 어디까지가 설명인지 흐려진다. */
.mcard-foot{display:flex;align-items:center;gap:var(--s3);margin-top:auto;padding-top:14px;
  border-top:1px solid var(--border-subtle);font-size:12px;color:var(--text-secondary);flex-wrap:wrap}
.mcard-tags{display:inline-flex;align-items:center;gap:8px;margin-left:auto}
.meta{display:inline-flex;align-items:center;gap:5px}
.meta svg{width:13px;height:13px;flex:none}
.meta-cat{color:var(--text-secondary)}
.meta-cat:hover{color:var(--brand);opacity:1}
.kind-tag{font-family:var(--font-mono);font-size:10px;letter-spacing:.06em;color:var(--text-secondary);
  border:1px solid var(--border-subtle);border-radius:4px;padding:1px 5px}

/* 아이콘 배지 — 카드 우측 상단(레퍼런스의 서비스 로고 자리) */
.ico{width:48px;height:48px;border-radius:12px;background:var(--tint);color:var(--brand);
  display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}
.ico svg{width:22px;height:22px}
.ico-lg{width:88px;height:88px;border-radius:20px}
.ico-lg svg{width:40px;height:40px}
.ico-sm{width:36px;height:36px;border-radius:10px}
.ico-sm svg{width:17px;height:17px}

/* ── 섹션 ── */
.sec{margin-bottom:var(--s12)}
.sec-h{display:flex;align-items:baseline;gap:10px;margin-bottom:var(--s4);flex-wrap:wrap}
.sec-h h2{margin:0;font-size:20px;font-weight:700;letter-spacing:-.01em;color:var(--text-primary)}
.sec-note{font-size:13px;color:var(--text-secondary)}
.sec-more{margin-left:auto;flex:none}
.link-more{font-size:13px;font-weight:600}

/* ── 목록 머리말 ── */
.page-head{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;padding-top:var(--s8)}
/* 제목 줄에 올라오는 컨트롤(검색·버튼)은 baseline 이 아니라 가운데 정렬이다 —
   38px 상자를 글자 baseline 에 맞추면 아래로 튀어나온다(2026-08-27 렌더 실측). */
.page-head .search,.page-head .btn{align-self:center}
.page-title{font-size:28px;font-weight:700;letter-spacing:-.02em;margin:0;color:var(--text-primary)}
.page-desc{font-size:14px;color:var(--text-secondary);margin:var(--s2) 0 var(--s6)}
.muted-n{font-size:13px;font-weight:400;color:var(--text-secondary)}
.count-n{font-family:var(--font-mono);font-size:14px;font-weight:400;color:var(--text-secondary)}
.chips{display:flex;flex-wrap:wrap;gap:var(--s2);margin:0 0 var(--s6)}
.chip{display:inline-flex;align-items:center;height:28px;padding:0 12px;border-radius:var(--radius-pill);
  border:1px solid var(--border-subtle);background:var(--surface-card);font-size:12px;color:var(--text-secondary);
  transition:border-color .15s var(--ease),color .15s var(--ease)}
.chip:hover{border-color:var(--brand);color:var(--brand);opacity:1}
.chip.is-active{background:var(--text-primary);border-color:var(--text-primary);color:var(--bg-page);font-weight:500}
.empty{border:1px dashed var(--border-subtle);border-radius:20px;padding:60px 40px;text-align:center}
.empty-t{font-size:15px;font-weight:600;color:var(--text-primary)}
.empty-d{font-size:13px;color:var(--text-secondary);margin-top:var(--s1)}

/* ── 상세 ── */
.back{display:inline-flex;font-size:13px;color:var(--text-secondary);padding-top:var(--s6);
  transition:color .15s var(--ease)}
.back:hover{color:var(--brand);opacity:1}
.dt-head{display:flex;align-items:flex-start;gap:var(--s6);margin-top:var(--s6)}
.dt-title{font-size:30px;font-weight:700;letter-spacing:-.02em;margin:0;color:var(--text-primary)}
.dt-slug{display:block;margin-top:6px;font-family:var(--font-mono);font-size:13px;color:var(--text-secondary)}
.dt-act{margin-top:var(--s4);display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap}
/* 지표 바 — 레퍼런스의 "MCP 상태 · 제작 · Tools · Tool call" 자리.
   숫자를 문장에 섞지 않고 한 줄에 세워 두면 무엇을 보는 물건인지 한눈에 잡힌다. */
.stats{display:grid;grid-template-columns:repeat(4,1fr);margin:var(--s8) 0 var(--s8);
  border-top:1px solid var(--border-subtle);border-bottom:1px solid var(--border-subtle);padding:18px 0}
.stat{text-align:center;padding:0 var(--s4);border-left:1px solid var(--border-subtle)}
.stat:first-child{border-left:0}
.stat-l{display:block;font-size:12px;color:var(--text-secondary)}
.stat-v{display:block;margin-top:4px;font-size:16px;font-weight:700;color:var(--text-primary)}
/* 분류는 그 분류의 목록으로 가는 문이다 — 링크지만 지표 바의 다른 값과 같은 무게로 보인다. */
.stat-v .stat-link{color:var(--text-primary)}
.stat-v .stat-link:hover{color:var(--brand);opacity:1}
.stat-v .dot{display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--state-up);
  margin-right:6px;vertical-align:middle}
/* 지표 바를 설명하는 한 줄. 위(설명 대상)에 붙이고 아래(다음 구획)와는 떨어뜨린다 —
   클래스에 규칙이 없어 다음 제목과 붙어 보였다(육안 검수 2026-08-25). */
.stats-note{margin:calc(var(--s6) * -1) 0 var(--s8)}
/* 위 여백이 0 이라 제목·슬러그 블록에 그대로 붙어 있었다(2026-08-29 사용자 지적).
   .dt-head 는 아이콘이 큰 flex 블록이라 자체 아래 여백이 없다 — 그 간격을 여기서 준다. */
.dt-desc{font-size:15px;color:var(--text-primary);line-height:1.8;margin:var(--s6) 0 var(--s8);white-space:pre-line}
/* 탭은 링크다(?tab=) — 자바스크립트 없이 동작하고 주소로 공유된다. */
.dt-tabs{display:flex;gap:var(--s6);border-bottom:1px solid var(--border-subtle);margin-bottom:var(--s6)}
.dt-tab{padding:12px 0;font-size:14px;color:var(--text-secondary);border-bottom:2px solid transparent;
  transition:color .15s var(--ease),border-color .15s var(--ease)}
.dt-tab:hover{color:var(--text-primary);opacity:1}
.dt-tab.is-active{color:var(--text-primary);font-weight:700;border-bottom-color:var(--text-primary)}
.panel{border:1px solid var(--border-subtle);border-radius:20px;background:var(--surface-card);padding:var(--s6)}
/* 상세의 "정보" 패널은 항목이 늘 1~2줄인데 본문 전체 폭(1008px)을 써서 오른쪽 2/3 가
   비었다(2026-08-30 사용자 지적: "상자 안에 글자가 여백이 안 맞는다"). 여백 자체는
   대칭이었고 — 원인은 넓은 상자에 짧은 내용이었다. 두 줄이면 나란히 놓아 채운다.
   좁아지면 auto-fit 이 알아서 한 줄로 돌아온다.
   구분선(.kv 의 border-top)은 여기서 지운다 — 열이 하나인지 둘인지를 CSS 가 알 수 없어
   "첫 행만 선 없음"을 정확히 표현할 방법이 없다. 항목이 두어 개뿐이라 여백으로 충분하다. */
.panel-wide{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));
  column-gap:var(--s8);row-gap:var(--s3)}
.panel-wide>.kv{border-top:0;padding:0}
.panel + .panel{margin-top:var(--s3)}
.panel-h{font-size:15px;font-weight:700;color:var(--text-primary);margin:0 0 var(--s3)}
/* 제목(.page-head) 바로 아래 첫 섹션이 붙어 보였다 — 화면의 시작이 어디인지 흐려진다. */
.page-head + .panel-h, .page-head + .two-col .panel-h{margin-top:var(--s2)}
.two-col section + section{margin-top:0}
/* 짧은 패널 둘을 나란히. 좁아지면 자동으로 한 줄씩 내려간다. */
.two-col{display:grid;grid-template-columns:repeat(auto-fit,minmax(340px,1fr));gap:var(--s6);align-items:start}
.two-col > .panel-h{margin-top:0}
.kv{display:flex;gap:var(--s4);font-size:14px;padding:9px 0;border-top:1px solid var(--border-subtle)}
.kv:first-child{border-top:0}
/* 라벨 칸이 넓으면 값이 멀어져 한 줄을 눈으로 두 번 읽는다 — 붙여 둔다. */
.kv-k{flex:0 0 92px;color:var(--text-secondary);font-size:13px}
.kv-v{flex:1;min-width:0;color:var(--text-primary)}
.kv-v code{font-family:var(--font-mono);font-size:12px;background:var(--bg-subtle);border-radius:6px;padding:2px 6px}
/* 도구 목록은 이름이 곧 식별자다 — 모노로 세우고 칸을 넓혀 설명과 겹치지 않게 한다. */
.panel-tools .kv-k{flex:0 0 220px;font-family:var(--font-mono);font-size:12px;color:var(--text-primary)}
/* 에이전트 프롬프트 — 붙여넣어 쓰는 값이라 원문 그대로 보인다. 길면 상자만 스크롤한다. */
.prompt-box{max-height:360px;overflow:auto;white-space:pre-wrap;word-break:keep-all;overflow-wrap:anywhere}
.dt-hint{font-size:13px;color:var(--text-secondary);border:1px dashed var(--border-subtle);
  border-radius:12px;padding:var(--s4) var(--s6)}
.dt-note{font-size:13px;color:var(--text-secondary)}

/* ── 내 연결: 좌 목록 · 우 연결 패널 (레퍼런스 도구함) ── */
/* ── 상세 화면: 본문 + 우측 레일 ── */
/* 레퍼런스(skillsmp·skillshop)가 공통으로 쓰는 구조다. 행동을 오른쪽 카드에 모으면
   본문을 읽다가도 "어떻게 쓰나"가 늘 시야에 있다. */
.dt-grid{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:var(--s8);align-items:start}
.dt-main{min-width:0}
/* sticky 는 헤더(64) 아래에 붙인다 — 스크롤해도 행동이 화면에 남는다.
   레일이 화면보다 길어질 수 있으므로(주소 여러 개) 높이를 재고 넘치면 레일만 스크롤한다 —
   상한이 없으면 sticky 로 고정된 뒤 아래쪽을 영영 못 본다. */
.dt-side{position:sticky;top:84px;max-height:calc(100vh - 104px);overflow-y:auto}
/* 여기 원래 var(--s5) 였다 — 그런 토큰은 없다(4·8·12·16·24·32·48 뿐).
   var() 가 없는 변수를 가리키면 그 선언은 unset → padding:0 이 되고, .panel 의 24px 로
   폴백되지도 않는다(캐스케이드에서 .dt-rail 이 이미 이겼다). 그래서 카드 안 버튼·주소가
   테두리를 뚫고 나왔다(사용자 지적 2026-08-26). 레일은 320px 로 좁으니 본문 카드보다
   한 단계 좁게 — 척도 위의 값으로 쓴다. */
.dt-rail{padding:var(--s4)}
.dt-sep{height:1px;background:var(--border-subtle);margin:var(--s4) 0}
/* 구분선 바로 뒤 항목은 자기 윗줄을 그리지 않는다 — 선이 두 개로 겹쳐 보인다. */
.dt-sep + .kv{border-top:0}
/* 레일 안에서는 버튼이 카드 폭을 채운다 — 좁은 칸에서 라벨 길이대로 두면 들쭉날쭉하다. */
.btn-block{display:flex;width:100%;justify-content:center}
.dt-rail .dt-act{display:block}
.dt-rail .dt-note{display:block;margin-top:var(--s2);font-size:12px;line-height:1.6}
.dt-rail .kv{gap:var(--s3)}
.dt-rail .kv-k{flex:0 0 64px}
/* 주소 옆 경고 — 붉게, 그러나 작게. 이 카드에서 유일하게 색을 쓰는 자리다. */
.rail-warn{font-size:12px;line-height:1.6;color:var(--state-down);border-left:2px solid var(--state-down);
  padding-left:8px;margin:var(--s3) 0 0}
/* 레일 아래쪽의 보조 링크(내 연결에서 전체 보기). 버튼과 경쟁하지 않게 글자로만 둔다. */
.rail-more{display:inline-block;margin-top:var(--s3);font-size:12px;color:var(--text-secondary)}
.rail-more:hover{color:var(--brand);opacity:1}
.rail-sub{font-size:12px;color:var(--text-secondary);margin-bottom:var(--s2)}
.rail-addr + .rail-addr{margin-top:var(--s3)}
.rail-addr-n{display:flex;align-items:center;gap:var(--s2);font-size:13px;font-weight:600;color:var(--text-primary)}
/* 좁은 레일에서는 복사 버튼도 작아야 한다 — 기본 높이(34)면 이름 줄이 두 배로 두꺼워진다. */
.rail-addr-n .btn-sm{height:26px;padding:0 10px;font-size:12px;flex:none}
/* 레일 안의 주소는 카드 폭에 맞춘 작은 글자 — 12px 아래로는 모노가 읽히지 않는다. */
.dt-rail .addr{font-size:12px}

/* 브레드크럼 — 어디에서 왔고 무엇의 하위인지. */
.crumb{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding-top:var(--s8);
  font-size:13px;color:var(--text-secondary)}
.crumb a{color:var(--text-secondary)}
.crumb a:hover{color:var(--brand);opacity:1}
.crumb-sep{color:var(--border-subtle)}
.crumb-now{color:var(--text-primary);font-weight:600}

.my-grid{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:var(--s8);align-items:start}
.my-side{position:sticky;top:88px;display:flex;flex-direction:column;gap:var(--s3)}
.stack-sm{display:flex;flex-direction:column;gap:var(--s3)}
.item{background:var(--surface-card);border:1px solid var(--border-subtle);border-radius:20px;
  padding:var(--s6);transition:border-color .15s var(--ease)}
.item:hover{border-color:var(--brand)}
.item-top{display:flex;align-items:center;gap:var(--s3)}
.item-name{font-weight:700;font-size:15px;color:var(--text-primary)}
.item-slug{display:block;margin-top:2px;font-family:var(--font-mono);font-size:11px;color:var(--text-secondary)}
.item-desc{font-size:13px;color:var(--text-secondary);margin:var(--s3) 0 0}
.item-foot{display:flex;align-items:center;gap:var(--s3);margin-top:var(--s3);font-size:13px}
.panel-link{display:flex;align-items:center;gap:10px;width:100%;padding:14px 0;font-size:14px;
  color:var(--text-primary);border-top:1px solid var(--border-subtle);
  background:none;border-left:0;border-right:0;border-bottom:0;cursor:pointer;font-family:inherit;text-align:left}
.panel-link:first-of-type{border-top:0}
.panel-link:hover{color:var(--brand);opacity:1}
.panel-link .push{font-size:12px;color:var(--text-secondary)}
.panel-note{font-size:12px;color:var(--text-secondary);line-height:1.6;margin-top:var(--s3)}

/* ── 에이전트 세트 (2026-08-28 · 2026-08-29 재설계) ──
   1차에서는 카드를 전부 펼쳐 두고 버튼을 평평하게 늘어놓았다. 에이전트 11개·스킬 5개인
   실제 데이터에서 두 개만 봐도 화면이 찼고, 버튼 8개가 한 카드를 채웠다.
   목록의 일은 **고르게 하는 것**이라 기본을 접고, 펼치면 설치 절차가 순서대로 나온다. */
.as{border-left:3px solid var(--brand);padding:0}
.as-sum{display:flex;align-items:flex-start;gap:var(--s3);padding:var(--s4) var(--s6);
  cursor:pointer;list-style:none;user-select:none}
.as-sum::-webkit-details-marker{display:none}
/* 펼침 표시는 오른쪽 끝에 — 개수 옆이라 "여기를 누르면 열린다"가 읽힌다. */
.as-sum::after{content:'▸';margin-left:var(--s2);color:var(--text-secondary);flex:0 0 auto;line-height:1.6}
.as[open]>.as-sum::after{content:'▾'}
.as-sum:hover .item-name{color:var(--brand)}
.as-sum-t{flex:1;min-width:0}
/* 설명은 한 줄로 자른다 — 목록에서는 고르는 데 필요한 만큼만 보인다. */
.as-desc{margin-top:6px;font-size:13px;color:var(--text-secondary);line-height:1.5;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.as[open] .as-desc{white-space:normal;overflow:visible}
.as-cnt{flex:0 0 auto;font-size:12px;color:var(--text-secondary);font-variant-numeric:tabular-nums;line-height:1.6}
.as-body{padding:0 var(--s6) var(--s6);border-top:1px solid var(--border-subtle);margin-top:var(--s2)}

/* 설치 절차 — 번호가 곧 순서다. ol 기본 마커는 쓰지 않는다(원 안의 숫자가 필요하다). */
.as-steps{list-style:none;margin:var(--s4) 0 0;padding:0;display:flex;flex-direction:column;gap:var(--s4)}
.as-step{display:flex;gap:var(--s3);align-items:flex-start}
.as-step-n{flex:0 0 auto;width:22px;height:22px;border-radius:50%;background:var(--brand);
  color:var(--on-brand);font-size:12px;font-weight:700;display:flex;align-items:center;justify-content:center}
.as-step-b{flex:1;min-width:0}
.as-step-t{font-size:13px;font-weight:600;color:var(--text-primary);margin-bottom:var(--s2)}
.as-act{display:flex;flex-wrap:wrap;gap:var(--s2)}

.as-parts{display:flex;align-items:flex-start;gap:var(--s3);margin-top:var(--s6);
  padding-top:var(--s4);border-top:1px solid var(--border-subtle)}
.as-parts-l{flex:0 0 auto;font-size:12px;font-weight:600;color:var(--text-secondary);line-height:28px}
/* .chips 의 기본 아래 여백(24px)은 독립 블록용이다. 카드 안에서는 그만큼이 빈칸으로 남는다. */
.as-chips{margin:0}
.as-foot{margin-top:var(--s3)}
/* 같은 주소가 두 곳에 펼쳐져 있으면 어느 쪽이 진짜인지 흐려진다 — 접어 두고 필요할 때 편다. */
.as-more>summary{cursor:pointer;font-size:13px;color:var(--text-secondary);
  padding:var(--s2) 0;list-style:none;user-select:none}
.as-more>summary::-webkit-details-marker{display:none}
/* 마커와 글자 사이는 margin 으로 띄운다 — content 의 후행 공백은 HTML 공백 축소로 사라진다. */
.as-more>summary::before{content:'▸';display:inline-block;margin-right:6px}
.as-more[open]>summary::before{content:'▾'}
.as-more>summary:hover{color:var(--brand)}
.as-addrs{display:flex;flex-direction:column;gap:var(--s3);margin-top:var(--s2)}
.as-addr-h{display:flex;align-items:center;gap:var(--s2)}
.as-addr-h .item-slug{margin-top:0}
.mt6{margin-top:var(--s6)}

/* ── 마이페이지 (2026-08-28 · 2026-08-29 재구성) ──
   1차는 큰 숫자 타일을 맨 위에 놓아 계정 화면이 대시보드처럼 보였다. 주역은 내 계정이므로
   요약은 내 정보 카드 안, 등급 줄 바로 아래로 내린다 — "이 등급이 이만큼"으로 읽히게. */
.ac-scope{margin-top:var(--s4);padding-top:var(--s4);border-top:1px solid var(--border-subtle)}
.ac-scope-h{font-size:12px;font-weight:600;color:var(--text-secondary)}
/* 숫자는 굵게, 라벨은 옅게 — 한 줄에 흐르되 좁아지면 접힌다(타일을 만들지 않는다). */
.ac-scope-n{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s4);margin-top:var(--s2);
  font-size:13px;color:var(--text-secondary)}
.ac-scope-n b{font-size:16px;color:var(--text-primary);margin-right:3px;font-variant-numeric:tabular-nums}
.ac-scope-act{display:flex;flex-wrap:wrap;gap:var(--s2);margin-top:var(--s3)}
/* 받아 간 기록 — 시각·종류·항목 세 값이라 표다. kv 두 칸에 넣으면 날짜가 접힌다. */
.ac-dl td,.ac-dl th{padding:9px var(--s3) 9px 0}
.ac-dl-ts{white-space:nowrap;font-variant-numeric:tabular-nums;color:var(--text-secondary);font-size:13px}
.ac-dl code{font-family:var(--font-mono);font-size:12px}

@media (max-width:900px){
  .ovs{grid-template-columns:repeat(2,minmax(0,1fr))}
  .top-in{gap:var(--s4);height:56px}
  .top-nav{gap:var(--s4);font-size:13px}
  .top-right .muted-n{display:none}
  .hero{padding:var(--s8) 0 var(--s6)}
  .hero-title{font-size:28px}
  .steps{grid-template-columns:1fr;gap:var(--s4);padding-bottom:var(--s8);margin-bottom:var(--s8)}
  .cards{grid-template-columns:1fr}
  .my-grid{grid-template-columns:1fr;gap:var(--s6)}
  .dt-grid{grid-template-columns:1fr;gap:var(--s6)}
  .side-shell{grid-template-columns:1fr;gap:var(--s4)}
  .side{position:static;padding-top:var(--s4)}
  /* 좁은 화면에서는 메뉴가 가로로 흐른다 — 세로로 쌓으면 본문이 화면 밖으로 밀린다. */
  .side-group{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
  .side-h{width:100%;margin-bottom:2px}
  /* 좁은 화면에서는 레일이 본문 아래로 내려간다 — sticky 때 걸어둔 높이 제한도 함께 푼다.
     안 풀면 카드가 화면 높이에서 잘리고 카드 안에 스크롤바가 생긴다. */
  .dt-side{position:static;max-height:none;overflow:visible}
  .my-side{position:static}
  .stats{grid-template-columns:repeat(2,1fr);gap:var(--s4) 0}
  .stat:nth-child(3){border-left:0}
  .dt-head{gap:var(--s4)}
  .ico-lg{width:64px;height:64px;border-radius:16px}
  .ico-lg svg{width:30px;height:30px}
  .dt-title{font-size:24px}
  .page-title{font-size:22px}
  .search{width:100%}
  .search-push{margin-left:0}
}

/* 로고는 라이트·다크 두 벌이다. 어두운 배경에 진한 로고를 그대로 두면 거의 안 보인다(실측).
   filter:invert 로 때우면 파란 브랜드색이 주황으로 뒤집힌다 — 공식 화이트 자산을 쓴다. */
.logo-light{display:block} .logo-dark{display:none}
@media (prefers-color-scheme: dark){ .logo-light{display:none} .logo-dark{display:block} }
:root[data-theme="dark"] .logo-light{display:none}
:root[data-theme="dark"] .logo-dark{display:block}
:root[data-theme="light"] .logo-light{display:block}
:root[data-theme="light"] .logo-dark{display:none}

/* 로그인·바인딩·인증실패 화면(login.js) 전용. 기존 .notice/.btn/.row 규칙은 그대로 두고 얹어서만 쓴다 —
   다른 화면(내 연결·관리자 등)이 그 규칙에 의존한다(task-6 리뷰 (C)(D)(F)). */
/* 오류를 안내와 구분한다. 색만으로 구분하지 않는다(색각 이상 대응) — login.js 가 "오류 — " 텍스트 접두를 함께 낸다. */
.notice-error{color:var(--state-down);border-left-color:var(--state-down)}
/* 비활성 제공자 버튼 — <span> 이라 원래도 눌리지 않지만, .btn-secondary 그대로면 흰 버튼처럼 눌릴 것처럼 보인다. */
.btn-disabled{opacity:.5;cursor:not-allowed}
/* 로그인 제공자 버튼 목록 — 라벨 길이와 무관하게 폭을 컨테이너에 맞춰 통일한다(세로 스택 + 폭 100%). */
.providers{display:flex;flex-direction:column;gap:var(--s3)}
.providers .btn{width:100%}
/* ── 제공자 브랜드 버튼 — 두 버튼이 똑같은 파란 상자면 무엇으로 들어가야 하는지
   한 번 더 읽어야 한다(사용자 지적 2026-08-27). 브랜드 색·로고로 즉시 갈리게 한다. */
.btn-provider{display:flex;align-items:center;justify-content:center;gap:10px;height:48px;
  border-radius:12px;font-weight:600;font-size:15px}
.provider-logo{width:20px;height:20px;flex:none}
/* Feishu 브랜드 블루(#3370FF)는 라이트·다크 공통 — 브랜드 색은 테마를 안 탄다 */
.btn-feishu{background:#3370ff;color:#fff}
.btn-feishu:hover{background:#2a5fd9;color:#fff}
.btn-google{background:var(--google-btn-bg);color:var(--google-btn-fg);border:1px solid var(--google-btn-border)}
.btn-google:hover{background:var(--google-btn-hover);color:var(--google-btn-fg);border-color:var(--google-btn-border)}

/* 계정 드롭다운의 테마 3단 토글 소버튼 — .chip 은 목록 필터용이라 크기가 안 맞는다. */
.acct-theme button{border:1px solid var(--border-subtle);background:transparent;color:var(--text-secondary);
  border-radius:12px;padding:2px 10px;font-size:12px;cursor:pointer}
.acct-theme button.is-active{background:var(--tint);color:var(--brand);border-color:var(--brand)}
.acct-theme span{display:flex;gap:4px}
