/* Quanect 컴포넌트 — tokens.css의 시맨틱 토큰만 쓴다. 색을 직접 쓰지 않는다.
   채움 배경은 최소로: 페이지 바탕, 카드 한 겹, Primary/Danger 버튼, 코드 블록, 떠 있는 요소(토스트·메뉴)뿐이다.
   상태·분류·알림·탭·입력창·빈 화면은 배경 없이 글자색, 아이콘, 테두리로 표시한다. */

* { box-sizing: border-box; }
/* 스크롤바 자리를 항상 확보해서, 내용이 짧은 페이지와 긴 페이지가 같은 좌우 위치를 쓴다 */
html { -webkit-text-size-adjust: 100%; scrollbar-gutter: stable; }
body {
  margin: 0; min-height: 100dvh; display: flex; flex-direction: column;
  font: var(--fw-regular) var(--fs-body)/var(--lh-body) var(--font-sans);
  color: var(--text); background: var(--bg);
  word-break: keep-all; overflow-wrap: break-word; -webkit-font-smoothing: antialiased;
}
a { color: var(--primary-text); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 4px; }
::selection { background: var(--primary-soft); }
h1, h2, h3 { margin: 0 0 .4em; text-wrap: balance; letter-spacing: -0.02em; }
h1 { font-size: var(--fs-title-1); line-height: var(--lh-title-1); font-weight: var(--fw-bold); }
h2 { font-size: var(--fs-title-2); line-height: var(--lh-title-2); font-weight: var(--fw-semibold); }
h3 { font-size: var(--fs-body); font-weight: var(--fw-semibold); }
p { margin: 0 0 1em; text-wrap: pretty; }
code, kbd, pre, .mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
:not(pre) > code { padding: 0 .2em; font-size: .9em; color: var(--text); }
.display { font-size: var(--fs-display); line-height: var(--lh-display); font-weight: var(--fw-bold); letter-spacing: -0.03em; }
.muted { color: var(--text-muted); }
.faint { color: var(--text-faint); }
.small { font-size: var(--fs-body-sm); line-height: var(--lh-body-sm); }
.caption { font-size: var(--fs-caption); line-height: var(--lh-caption); }
.name { font-weight: var(--fw-semibold); white-space: nowrap; }
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.skip-link { position: absolute; left: 12px; top: -48px; z-index: 100; background: var(--primary); color: var(--on-primary); padding: 8px 14px; border-radius: var(--radius-sm); }
.skip-link:focus { top: 12px; }

/* 아이콘: 24 그리드, 선 1.75, currentColor */
.i { width: 16px; height: 16px; flex: none; }
.i--lg { width: 18px; height: 18px; }
.i--xl { width: 34px; height: 34px; }

/* 레이아웃 */
.container { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }
.stack { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
.stack-sm { display: flex; flex-direction: column; gap: var(--space-3); min-width: 0; }
.stack-lg { display: flex; flex-direction: column; gap: var(--space-8); min-width: 0; }
.row { display: flex; gap: var(--space-3); flex-wrap: wrap; align-items: center; }
.row--between { justify-content: space-between; }
.grow { flex: 1 1 auto; min-width: 0; }
.cols { display: grid; gap: var(--space-8) var(--space-12); grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.main { flex: 1 0 auto; padding: var(--space-12) 0 80px; }
.main > .container { display: flex; flex-direction: column; gap: var(--space-8); }
.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap; }
.page-head h1 { margin: 0; }
.page-head p { margin: 8px 0 0; max-width: 62ch; }

/* 헤더: 본문(--bg)보다 한 단계 밝은 --surface + 아래로 떨어지는 그림자. 다크·라이트 규칙이 같다. 메뉴 항목에 배경 없음 */
.site-header { background: var(--surface); box-shadow: var(--shadow-header); position: sticky; top: 0; z-index: var(--z-header); }
.header-row { display: flex; align-items: center; gap: var(--space-4); min-height: var(--header-height); }
.brand img { display: block; height: 28px; width: auto; }
/* 오른쪽 버튼 묶음: 같은 종류의 컨트롤은 8px로 붙이고, 로고·메뉴·묶음 사이(16px)와 구분한다 */
.header-actions { display: flex; align-items: center; gap: var(--space-2); }
.nav { display: flex; gap: 4px; flex: 1 1 auto; margin-left: 8px; }
.nav a { color: var(--text-muted); padding: 6px 12px; font-size: var(--fs-body-sm); font-weight: var(--fw-semibold); }
.nav a:hover { color: var(--text); text-decoration: none; }
.nav a[aria-current="page"] { color: var(--primary-text); }
.avatar { width: var(--control-sm); height: var(--control-sm); border-radius: 8px; border: 1px solid var(--border); color: var(--text-muted); display: grid; place-items: center; font-size: var(--fs-caption); font-weight: var(--fw-semibold); }
/* 좁은 화면: 로고 ↔ 버튼은 양 끝, 메뉴는 헤더 안 둘째 줄(가로 스크롤)로 내려 이동 수단을 유지한다 */
@media (max-width: 640px) {
  .header-row { flex-wrap: wrap; row-gap: 0; padding-block: calc((var(--header-height) - var(--control-sm)) / 2); min-height: 0; }
  .brand { margin-right: auto; }
  .nav { order: 3; flex: 0 0 100%; margin: var(--space-2) calc(var(--gutter) * -1) -6px; padding: 0 calc(var(--gutter) - 12px); overflow-x: auto; }
  .nav a { padding: 10px 12px; white-space: nowrap; }
}

/* 테마별 로고 */
img.logo-light { display: none; }
:root[data-theme="light"] img.logo-dark { display: none; }
:root[data-theme="light"] img.logo-light { display: block; }

/* 버튼: 채움은 Primary·Danger만. 나머지는 테두리 또는 글자만 */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-height: 40px; padding: 0 16px; font: inherit; font-size: var(--fs-body-sm); font-weight: var(--fw-semibold); line-height: 1;
  border-radius: var(--radius-sm); border: 1px solid var(--border-strong); background: transparent; color: var(--text); cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.btn:hover { border-color: var(--text); text-decoration: none; }
.btn:active { transform: scale(.98); }
.btn:disabled { opacity: .45; cursor: not-allowed; transform: none; }
.btn[aria-busy="true"] { opacity: .7; pointer-events: none; }
.btn--primary { background: var(--primary); color: var(--on-primary); border-color: transparent; }
.btn--primary:hover { background: var(--primary-hover); border-color: transparent; }
.btn--danger { background: var(--danger-solid); color: var(--on-danger); border-color: transparent; }
.btn--danger:hover { background: var(--danger-hover); border-color: transparent; }
.btn--danger-ghost { color: var(--danger-text); border-color: var(--border); }
.btn--danger-ghost:hover { border-color: var(--danger-text); }
.btn--ghost { border-color: transparent; color: var(--text-muted); }
.btn--ghost:hover { color: var(--text); border-color: transparent; }
.btn--sm { min-height: var(--control-sm); padding: 0 12px; font-size: var(--fs-caption); }
.btn--lg { min-height: 52px; padding: 0 24px; font-size: var(--fs-body); }
.btn--block { width: 100%; }
.btn-group { display: flex; gap: var(--space-2); flex-wrap: wrap; align-items: center; }
.icon-btn { display: inline-grid; place-items: center; width: var(--control-sm); height: var(--control-sm); padding: 0; background: transparent; border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text-muted); cursor: pointer; }
.icon-btn:hover { color: var(--text); border-color: var(--text-faint); }
/* 터치: 기본 버튼은 44px. 작은 버튼과 아이콘 버튼은 같은 --control-sm(36px)로 높이를 맞춘다 */
@media (pointer: coarse) { .btn { min-height: var(--touch-min); } .btn--sm { min-height: var(--control-sm); } .btn--lg { min-height: 52px; } }

/* 입력: 채움 없이 테두리만 */
.field { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.field > label { font-size: var(--fs-body-sm); font-weight: var(--fw-semibold); }
.input {
  width: 100%; min-height: 44px; padding: 0 14px; font: inherit; font-size: var(--fs-body); color: var(--text);
  background: transparent; border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.input::placeholder { color: var(--text-faint); }
.input:focus { outline: none; border-color: var(--primary); box-shadow: var(--ring); }
.input[aria-invalid="true"] { border-color: var(--danger-text); }
.help { font-size: var(--fs-caption); line-height: var(--lh-caption); color: var(--text-muted); margin: 0; }
.help--error { color: var(--danger-text); }
.input-prefixed { display: flex; }
.input-prefixed .input { border-radius: var(--radius-sm) 0 0 var(--radius-sm); min-width: 0; }
.input-prefixed .suffix { display: flex; align-items: center; padding: 0 12px; font-size: var(--fs-body-sm); color: var(--text-muted); border: 1px solid var(--border-strong); border-left: 0; border-radius: 0 var(--radius-sm) var(--radius-sm) 0; white-space: nowrap; }
.check { display: flex; gap: 10px; align-items: flex-start; font-size: var(--fs-body-sm); }
.check input { width: 18px; height: 18px; margin: 2px 0 0; accent-color: var(--primary); }

/* 카드: 묶인 정보 영역을 빈 공간과 구분한다. 채움(--surface) 한 겹, 테두리 없음.
   카드 안에는 채움 요소를 넣지 않는다(입력창·배지·탭은 배경 없음). 카드 안 카드 금지 */
.card { background: var(--surface); border-radius: var(--radius); padding: var(--panel-padding); min-width: 0; }
.card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap; margin-bottom: var(--space-4); }
.card-head h2, .card-head h3 { margin: 0; }
/* 카드 사이 간격은 --space-4(16px): 한 묶음의 카드는 서로 가까워야 같은 계층으로 읽힌다 */
.card-list { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
.cols--cards { gap: var(--space-4); }
.card-title { font-size: var(--fs-body); font-weight: var(--fw-semibold); margin: 0; letter-spacing: -0.01em; }
/* 카드 안 표는 카드 가장자리에 맞추고 바깥 박스를 두지 않는다 */
.card .table-wrap { margin-inline: calc(var(--panel-padding) * -1); padding-inline: var(--panel-padding); }

/* 상태·분류: 배경 없이 글자색 + 아이콘 */
.badge { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-caption); font-weight: var(--fw-semibold); line-height: 1.4; color: var(--text-muted); white-space: nowrap; }
.badge .i { width: 14px; height: 14px; }
.badge--active, .badge--running { color: var(--success-text); }
.badge--warning { color: var(--warning-text); }
.badge--error { color: var(--danger-text); }
.tag { font-size: var(--fs-caption); color: var(--text-muted); }
.tag--accent { color: var(--primary-text); font-weight: var(--fw-semibold); }

/* 알림: 배경 없이 아이콘 + 글자. 오류·주의는 글자색도 바뀐다 */
.alert { display: flex; gap: 12px; align-items: flex-start; font-size: var(--fs-body-sm); color: var(--text); }
.alert > .i { color: var(--primary-text); margin-top: 3px; }
.alert--warning, .alert--warning > .i { color: var(--warning-text); }
.alert--error, .alert--error > .i { color: var(--danger-text); }
.alert p { margin: 0; }
/* 토스트는 떠 있는 요소라 채움 + 그림자를 쓴다 */
.toast { display: flex; gap: 12px; align-items: flex-start; padding: 13px 16px; background: var(--surface-2); border-radius: var(--radius); box-shadow: var(--shadow-md); font-size: var(--fs-body-sm); }
.toast .i { margin-top: 3px; }
.toast--success .i { color: var(--success-text); }
.toast--error .i { color: var(--danger-text); }
.toast--warning .i { color: var(--warning-text); }

/* 목록·표: 바깥 박스 없이 행 구분선만 */
.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: var(--fs-body-sm); }
th { text-align: left; font-size: var(--fs-caption); font-weight: var(--fw-semibold); color: var(--text-muted); padding: 10px 16px 10px 0; white-space: nowrap; }
td { padding: 14px 16px 14px 0; border-top: 1px solid var(--border-soft); min-height: 48px; vertical-align: middle; }
td.act, th.act { text-align: right; white-space: nowrap; width: 1%; padding-right: 0; }

/* 빈 화면: 박스 없이 가운데 정렬 */
.empty { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 6px; padding: 56px 24px; color: var(--text-muted); }
.empty .i--xl { color: var(--text-faint); margin-bottom: 6px; }
.empty h3 { color: var(--text); margin: 0; }
.empty p { max-width: 44ch; margin: 0 0 12px; }

/* 탭: 선택은 글자색과 굵기로만 */
.tablist { display: inline-flex; gap: 20px; }
.tab { font: inherit; font-size: var(--fs-body-sm); color: var(--text-muted); background: transparent; border: 0; padding: 8px 0; cursor: pointer; }
.tab:hover { color: var(--text); }
.tab[aria-selected="true"] { color: var(--primary-text); font-weight: var(--fw-semibold); }

/* 코드: 코드 블록만 오목한 채움을 허용한다 */
.codeblock { position: relative; }
.codeblock pre { margin: 0; padding: 14px 110px 14px 16px; background: var(--surface-inset); border-radius: var(--radius-sm); font-size: 13px; overflow-x: auto; }
.codeblock .btn { position: absolute; top: 8px; right: 8px; }

/* 공개 화면: 떠 있는 박스 대신 화면 전체를 두 영역으로 나눈다 (왼쪽 --surface, 오른쪽 --bg) */
.split { flex: 1 0 auto; display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); min-height: 100dvh; }
.split-side { background: var(--surface); padding: var(--space-12) var(--space-10); display: flex; flex-direction: column; justify-content: space-between; gap: var(--space-8); }
.split-side > img { align-self: flex-start; }
.split-side .code { font-size: clamp(4rem, 12vw, 7rem); font-weight: var(--fw-bold); letter-spacing: -0.05em; line-height: 1; margin: 0; color: var(--primary-text); }
.split-side .lede { font-size: var(--fs-title-1); line-height: var(--lh-title-1); font-weight: var(--fw-bold); letter-spacing: -0.02em; margin: 0; max-width: 14ch; }
.split-main { padding: var(--space-12) var(--gutter); display: flex; align-items: center; justify-content: center; }
@media (max-width: 800px) {
  .split { grid-template-columns: 1fr; grid-template-rows: auto 1fr; min-height: 100dvh; }
  /* 모바일에서는 영역이 헤더 한 줄(64px)이 된다: 콘솔 헤더와 같게 --surface + 아래 그림자 + 로고만 */
  .split-side { background: var(--surface); box-shadow: var(--shadow-header); position: relative; z-index: var(--z-header); min-height: var(--header-height); padding: 0 var(--gutter); flex-direction: row; align-items: center; justify-content: flex-start; gap: 0; }
  .split-side > img { align-self: center; }
  .split-side .lede, .split-side .caption, .split-side .code, .split-side .side-extra { display: none; }
  .split-main { align-items: flex-start; padding-top: var(--space-8); }
}
/* 공개 화면 폼 */
.auth-form { width: 100%; max-width: var(--maxw-narrow); display: flex; flex-direction: column; gap: var(--space-6); }
.auth-form .logo { height: 32px; width: auto; align-self: flex-start; }
.auth-form h1 { font-size: var(--fs-title-2); line-height: var(--lh-title-2); font-weight: var(--fw-semibold); margin: 0; }
.scope-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.scope-list li { display: flex; gap: 12px; align-items: flex-start; font-size: var(--fs-body-sm); }
.scope-list .i { color: var(--primary-text); margin-top: 3px; }
.scope-list .caption { display: block; color: var(--text-muted); }
.app-mark { width: 44px; height: 44px; display: grid; place-items: center; color: var(--text-muted); }
.link-row { display: flex; align-items: center; gap: 12px; color: var(--text-faint); }
.sep { text-align: center; color: var(--text-faint); font-size: var(--fs-caption); margin: 0; }

/* 좁은 화면: 이름·상태·작업만 남기고 부가 열은 숨긴다. 코드 블록의 복사 버튼은 아이콘만 남긴다 */
@media (max-width: 640px) {
  .hide-sm { display: none; }
  td, th { padding-right: 12px; }
  .codeblock pre { padding: 12px 52px 12px 14px; white-space: pre-wrap; word-break: break-all; }
  .codeblock .btn { top: 6px; right: 6px; width: var(--control-sm); min-height: var(--control-sm); height: var(--control-sm); padding: 0; }
  .codeblock .btn-label { display: none; }
}
