/* Vibe Coder Admin — 미니멀 다크 테마. CDN 의존 없음. */

@font-face {
    font-family: "Noto Sans Symbols 2";
    src: url("/static/fonts/NotoSansSymbols2-Regular.ttf") format("truetype");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
    unicode-range:
        U+00AB-00BB,
        U+2039-203B,
        U+2190-21FF,
        U+2300-23FF,
        U+2500-257F,
        U+2580-259F,
        U+25A0-25FF,
        U+2600-26FF,
        U+2700-27BF,
        U+3008-301B,
        U+2B00-2BFF,
        U+E000-F8FF;
}

* { box-sizing: border-box; }
:root {
    --bg: #0f1419;
    --bg-elev: #1a1f29;
    --bg-card: #1e2532;
    --border: #2a3142;
    --text: #e4e8ef;
    --text-dim: #8b94a8;
    --primary: #5e9eff;
    --accent: var(--primary);
    --primary-hover: #7eb4ff;
    --danger: #ff6b6b;
    --warn: #ffa94d;
    --ok: #69db7c;
    /* v1.100.0 — 상태칩 5-state 일관 팔레트: 대기중(노랑) / 중단됨(보라). */
    --wait: #fab005;
    --halt: #b197fc;
    --radius: 6px;
    --radius-hairline: 2px;
    --status-off: #3a4150;
    --shadow: 0 2px 8px rgba(0,0,0,0.3);
    --shadow-brand-icon: 0 2px 8px rgba(0,0,0,0.25);
    --shadow-drawer: -12px 0 32px color-mix(in srgb, var(--bg) 72%, transparent);
    --overlay-scrim: color-mix(in srgb, var(--bg) 78%, transparent);
    --console-bg: #0a0d12;
    --console-sticky-bg: #121a28;
    --console-scroll-thumb: #3b3b3b;
    --console-scroll-thumb-hover: #555;
    --console-bubble-fill: rgba(255,255,255,0.05);
    --console-assistant-fill: rgba(94,211,161,0.09);
    --console-assistant-border: rgba(94,211,161,0.18);
    --console-tool-fill: rgba(207,167,99,0.09);
    --console-tool-border: rgba(207,167,99,0.16);
    --console-tool-out-fill: rgba(142,160,194,0.08);
    --console-tool-out-border: rgba(142,160,194,0.14);
    --console-error-fill: rgba(255,107,107,0.11);
    --console-error-border: rgba(255,107,107,0.26);
    --console-sys-fill: rgba(108,122,147,0.15);
    --console-sys-text: #9aa7bd;
    --console-thinking-fill: rgba(138,127,176,0.14);
    --console-thinking-border: rgba(138,127,176,0.22);
    --console-assistant-accent: #5ed3a1;
    --console-tool-accent: #cfa763;
    --console-tool-out-accent: #8ea0c2;
    --console-gauge-vibe: #16a34a;
    --console-tui-font-family: "Cascadia Mono", "DejaVu Sans Mono", "Liberation Mono", "Noto Sans Mono", Consolas, "Courier New", "Noto Sans Symbols 2", "Noto Color Emoji", monospace;
    --context-read: #3a82f6;
    --context-create: #2dd4bf;
    --context-input: #ffb86b;
    --context-input-ring: rgba(255,184,107,0.45);
    --status-stopped-border: rgba(151, 117, 250, 0.4);
    --status-stopped-fill: rgba(151, 117, 250, 0.08);
    --radius-scroll-thumb: 5px;
    --radius-console-bubble: 14px;
    --radius-console-pill: 11px;
    --radius-badge: 9px;
    --shadow-floating-control: 0 4px 14px rgba(0,0,0,0.5);
}

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
    /* v1.16.0 — 가로 스크롤 차단 (자식이 부모 너비 초과 시 자체 overflow 처리). */
    overflow: hidden;
    background: var(--bg);
    color: var(--text);
    font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Apple SD Gothic Neo", sans-serif;
}

a { color: var(--primary); text-decoration: none; }
a:hover { color: var(--primary-hover); text-decoration: underline; }

/* ── Layout ──────────────────────────────────────────────────────── */

.layout {
    display: grid;
    grid-template-columns: 220px 1fr;
    /* v1.16.0 — 동적 viewport (`dvh`) → mobile 주소창 동적 height 도 정확.
       fallback: vh. 정확히 viewport 만 차지 + 자체 overflow 차단 → 사이드바와
       컨텐츠가 각자 자체 영역에서 스크롤. */
    height: 100vh;
    height: 100dvh;
    height: var(--app-viewport-height, 100dvh);
    overflow: hidden;
}
.layout.no-nav { grid-template-columns: 1fr; }
/* v1.6.2 — 사이드바 접힘. :root data-attribute (first paint 전 inline script 가
   localStorage 보고 set) + body class 둘 다 지원. JS toggle 은 두 곳 다 갱신. */
:root[data-sidebar-collapsed="1"] .layout,
.layout.sidebar-collapsed { grid-template-columns: 56px 1fr; }

.sidebar {
    background: var(--bg-elev);
    border-right: 1px solid var(--border);
    padding: 20px 14px 24px;
    display: flex;
    flex-direction: column;
    gap: 16px;
    align-items: stretch;
    /* v1.16.0 — 사이드바 자체는 viewport 안에 항상 100% 표시 (스크롤 X). nav-links
       가 길어지면 그 안에서만 자체 스크롤 (overflow: auto 가 nav-links 에 적용). */
    overflow: hidden;
    min-height: 0;
}

/* v1.7.6 — 브랜드: 아이콘 위 + 타이틀 아래 (column). 전체가 홈 link <a>.
   접힘 시 .brand-title 숨김 → 아이콘만 보임. */
.brand {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    text-decoration: none;
    color: var(--text);
    padding: 4px 0;
    transition: opacity 0.15s ease;
}
.brand:hover { opacity: 0.85; text-decoration: none; }
.brand-icon {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
    box-shadow: var(--shadow-brand-icon);
}
.brand-title {
    font-size: 18px;
    font-weight: 700;
    letter-spacing: -0.5px;
    line-height: 1;
}

/* v1.6.2 — 사이드바 상단 접기 버튼. v1.7.6 — brand 아래 가운데 배치.
   v1.7.10 — flex center 로 글리프 정확히 가운데 정렬 (이전엔 line-height 24px
   + height 28px mismatch 로 우하단으로 밀려 보였음). */
.sidebar-toggle {
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 6px;
    color: var(--text-dim);
    width: 36px;
    height: 28px;
    padding: 0;
    cursor: pointer;
    font: inherit;
    line-height: 1;
    flex-shrink: 0;
    align-self: center;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.sidebar-toggle:hover { background: var(--bg-card); color: var(--text); }

.mobile-nav-toggle,
.mobile-nav-backdrop {
    display: none;
}

.mobile-nav-toggle {
    background: transparent;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text-dim);
    width: 44px;
    height: 44px;
    padding: 0;
    cursor: pointer;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    gap: 4px;
    flex-shrink: 0;
}
.mobile-nav-toggle span {
    display: block;
    width: 16px;
    height: 2px;
    border-radius: var(--radius-hairline);
    background: currentColor;
}
.mobile-nav-toggle:hover,
body.mobile-nav-open .mobile-nav-toggle {
    background: var(--bg-card);
    color: var(--text);
}

/* v1.7.6 — 접힘 상태:
   - 브랜드 타이틀, nav 라벨, quota pill, username, logout 모두 숨김.
   - nav 아이콘은 보존 + 가운데 정렬.
   - brand-icon 도 살짝 축소 (40px) — 사이드바 폭 56px 안에 자연스럽게.
   - sidebar padding 좁힘 + center align. */
:root[data-sidebar-collapsed="1"] .layout .brand-title,
.layout.sidebar-collapsed .brand-title,
:root[data-sidebar-collapsed="1"] .layout .nav-links a .nav-label,
.layout.sidebar-collapsed .nav-links a .nav-label,
:root[data-sidebar-collapsed="1"] .layout .quota-pill,
.layout.sidebar-collapsed .quota-pill,
:root[data-sidebar-collapsed="1"] .layout .user-box .user,
.layout.sidebar-collapsed .user-box .user,
:root[data-sidebar-collapsed="1"] .layout .logout,
.layout.sidebar-collapsed .logout { display: none; }

:root[data-sidebar-collapsed="1"] .layout .sidebar,
.layout.sidebar-collapsed .sidebar { padding: 12px 8px; gap: 10px; align-items: center; }
:root[data-sidebar-collapsed="1"] .layout .brand-icon,
.layout.sidebar-collapsed .brand-icon { width: 40px; height: 40px; }
:root[data-sidebar-collapsed="1"] .layout .user-box,
.layout.sidebar-collapsed .user-box { padding-top: 0; border-top: none; }
:root[data-sidebar-collapsed="1"] .layout .sidebar-toggle,
.layout.sidebar-collapsed .sidebar-toggle { width: 32px; height: 32px; }
:root[data-sidebar-collapsed="1"] .layout .nav-links a,
.layout.sidebar-collapsed .nav-links a {
    justify-content: center;
    padding: 8px 0;
    gap: 0;
}

.nav-links {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 1;
    /* v1.16.0 — 사이드바 자체는 overflow: hidden. nav-links 가 viewport 보다 길면
       여기서만 세로 스크롤 (사이드바 다른 영역 — 브랜드 / quota / user-box — 은
       항상 보임). */
    overflow-y: auto;
    overflow-x: hidden;
    min-height: 0;
}
.nav-links a {
    padding: 8px 12px;
    border-radius: var(--radius);
    color: var(--text-dim);
    display: flex;
    align-items: center;
    gap: 10px;
    text-decoration: none;
}
.nav-links a .nav-icon {
    flex-shrink: 0;
    width: 20px;
    height: 20px;
    opacity: 0.85;
}
.nav-links a .nav-label {
    flex: 1;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.nav-links a:hover { background: var(--bg-card); color: var(--text); text-decoration: none; }
.nav-links a:hover .nav-icon { opacity: 1; }
.nav-links a.active { background: var(--bg-card); color: var(--text); font-weight: 600; }
.nav-links a.active .nav-icon { opacity: 1; }

.user-box {
    padding-top: 16px;
    border-top: 1px solid var(--border);
}
.user-box .user { font-size: 12px; color: var(--text-dim); margin-bottom: 8px; }

/* v1.3.2 — 전역 Claude 쿼타 pill (좌하단 사이드바, 유저명 직전). */
/* v1.158.2 — pill 간격 압축 (padding/margin/gap 축소) — 상단 메뉴 영역 확보. */
.quota-pill {
    padding: 3px 0;
    margin-top: 2px;
    border-top: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    gap: 4px;
}
/* v1.6.2 — 쿼타 헤더: "Claude" 라벨 + refresh 아이콘 버튼. */
/* v1.155.0 — 헤더 클릭으로 접기/펼치기. 접으면 헤더 한 줄에 대표 % 만 (qp-pct-compact). */
.quota-pill .qp-header {
    display: flex; justify-content: flex-start; align-items: center; gap: 6px;
    font-size: 11px; color: var(--text-dim); font-weight: 600;
    letter-spacing: 0.4px; text-transform: uppercase;
    cursor: pointer; user-select: none;
}
.quota-pill .qp-header::before {
    content: '▾'; font-size: 9px; color: var(--text-dim); flex: none;
    transition: transform .15s ease;
}
.quota-pill.collapsed .qp-header::before { transform: rotate(-90deg); }
.quota-pill .qp-header:focus-visible { outline: 1px solid var(--primary); outline-offset: 2px; border-radius: 3px; }
.quota-pill .qp-h-title { /* same as qp-header text */ }
.quota-pill .qp-rows { display: flex; flex-direction: column; gap: 4px; }
.quota-pill.collapsed .qp-rows { display: none; }
.quota-pill .qp-pct-compact {
    font-weight: 600; font-variant-numeric: tabular-nums;
    font-size: 11px; text-transform: none; letter-spacing: 0;
    display: inline-flex; align-items: center; gap: 2px; white-space: nowrap;
}
.quota-pill .qp-compact-sep { color: var(--text-dim); font-weight: 400; }
.quota-pill:not(.collapsed) .qp-pct-compact { display: none; }
/* v1.65.0 — 무선디버깅 pill (Claude 사용량 위). quota-pill 스타일 재사용 + 자체 body. */
.adb-pill { text-decoration: none; color: inherit; gap: 6px; }
.adb-pill:hover .adb-pill-body { color: var(--text); }
.adb-pill .adb-pill-body { font-size: 12px; color: var(--text-dim); display: flex; align-items: center; gap: 5px; }
.adb-pill .adb-dot {
    width: 8px; height: 8px; border-radius: 50%; background: var(--status-off); flex: none;
}
.adb-pill .adb-dot.on {
    background: var(--ok);
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--ok) 60%, transparent);
    animation: pstat-pulse 1.6s ease-in-out infinite;
}
.adb-pill .emu-dot-list {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: auto;
}
.adb-pill .emu-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--status-off);
    flex: none;
}
.adb-pill .emu-dot.idle {
    background: var(--ok);
}
.adb-pill .emu-dot.busy {
    background: var(--wait);
}
.adb-pill .emu-dot.stopped {
    background: var(--status-off);
}
:root[data-sidebar-collapsed="1"] .layout .adb-pill,
.layout.sidebar-collapsed .adb-pill { display: none; }
.quota-pill .qp-refresh {
    background: transparent; border: none; color: var(--text-dim);
    cursor: pointer; padding: 0 4px; font-size: 14px; line-height: 1;
    margin-left: auto;  /* v1.155.0 — 접은 상태(compact% 숨김)에서도 우측 고정 */
}
.quota-pill .qp-refresh:hover { color: var(--text); }
.quota-pill .qp-refresh:disabled { opacity: 0.5; cursor: wait; }
.quota-pill .qp-row { display: flex; flex-direction: column; gap: 3px; }
.quota-pill .qp-row-head {
    display: flex; justify-content: space-between; align-items: baseline;
    font-size: 11px;
}
.quota-pill .qp-label { color: var(--text-dim); }
.quota-pill .qp-pct { font-weight: 600; font-variant-numeric: tabular-nums; }
.quota-pill .qp-track {
    height: 4px; background: var(--bg-card); border-radius: var(--radius-hairline); overflow: hidden;
}
.quota-pill .qp-fill { height: 100%; }
.quota-pill .qp-reset {
    font-size: 10px; color: var(--text-dim); margin-top: 1px;
}
.logout {
    width: 100%;
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-dim);
    padding: 8px;
    border-radius: var(--radius);
    cursor: pointer;
    font: inherit;
}
.logout:hover { background: var(--bg-card); color: var(--text); }

.content {
    padding: 32px;
    max-width: 1200px;
    width: 100%;
    justify-self: center;
    /* v1.16.0 — 컨텐츠 영역 내 세로 스크롤만, 가로 스크롤 차단. min-height: 0 은
       grid 자식이 overflow 를 정상 처리하기 위함. box-sizing 으로 padding 포함. */
    overflow-y: auto;
    overflow-x: hidden;
    min-height: 0;
    box-sizing: border-box;
}
/* v1.16.0 — ProjectTabsTemplate 같이 자체적으로 100% viewport 안에 layout 을
   구성하는 page 용 변형. padding / max-width 제거, 내부 자식이 직접 100% 채움. */
.content.fullbleed {
    padding: 0;
    max-width: none;
    overflow: hidden;
}
/* v1.104.0 — 넓은 모니터에서 1200px 중앙정렬 대신 브라우저 폭을 효율적으로 쓰는 변형.
   fullbleed 와 달리 padding(여백)은 유지 — 일반 콘텐츠 페이지(홈/프로젝트/채팅/메모/
   터미널)가 가장자리에 붙지 않으면서 전체 폭을 활용. */
.content.wide {
    max-width: none;
}

/* v1.33.1 — 모바일(≤768px) 레이아웃은 아래 "작은 태블릿 / 큰 폰" 블록(가로 헤더
   nav)으로 단일화. 이전엔 여기에 또 다른 768px 블록(사이드바 56px 세로 collapsed)이
   있어 같은 breakpoint 에서 가로 헤더 블록과 cascade/specificity 충돌 → 상단 헤더
   메뉴 높이/라벨이 깨졌음(16차 이후 검토). 데스크톱 접기는 [data-sidebar-collapsed]
   룰이 그대로 담당. */

header h1 {
    margin: 0 0 24px;
    font-size: 24px;
    font-weight: 700;
}

/* v0.69.1 — heading + paragraph + dl/pre baseline (sub-page 들이 직접 h2/h3/pre 사용). */
h1 { margin: 0 0 24px; font-size: 24px; font-weight: 700; line-height: 1.3; }
h2 { margin: 24px 0 12px; font-size: 18px; font-weight: 700; line-height: 1.3; }
h3 { margin: 20px 0 10px; font-size: 15px; font-weight: 600; line-height: 1.3; color: var(--text); }
h4 { margin: 16px 0 8px; font-size: 13px; font-weight: 600; line-height: 1.3; color: var(--text-dim);
     text-transform: uppercase; letter-spacing: 0.5px; }
p { margin: 0 0 12px; }
ul, ol { margin: 0 0 12px; padding-left: 20px; }
ul li, ol li { margin-bottom: 4px; }
dl { display: grid; grid-template-columns: max-content 1fr; gap: 6px 12px; margin: 0; }
dt { color: var(--text-dim); }
dd { margin: 0; }
hr { border: none; border-top: 1px solid var(--border); margin: 20px 0; }

pre, code {
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}
pre {
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 12px 14px;
    font-size: 12.5px;
    line-height: 1.55;
    overflow-x: auto;
    margin: 0 0 12px;
    white-space: pre-wrap;
    word-break: break-word;
}
small { font-size: 12px; }
strong { font-weight: 600; }

/* ── Cards ───────────────────────────────────────────────────────── */

.grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 16px;
}

.card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 20px;
    box-shadow: var(--shadow);
}

.card h2 {
    margin: 0 0 12px;
    font-size: 14px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-dim);
    font-weight: 600;
}

.card dl { margin: 0; display: grid; grid-template-columns: max-content 1fr; gap: 6px 12px; }
.card dt { color: var(--text-dim); }
.card dd { margin: 0; }

.usage-card {
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.usage-card h2 { margin: 0; }
.usage-card-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
}
.usage-provider {
    display: inline-flex;
    align-items: center;
    max-width: 52%;
    min-height: 22px;
    padding: 3px 9px;
    border-radius: var(--radius-badge);
    border: 1px solid var(--border);
    background: var(--bg);
    color: var(--text-dim);
    font-size: 12px;
    font-weight: 600;
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.usage-provider.ok {
    color: var(--ok);
    border-color: color-mix(in srgb, var(--ok) 42%, var(--border));
    background: color-mix(in srgb, var(--ok) 10%, var(--bg-card));
}
.usage-provider.warn {
    color: var(--warn);
    border-color: color-mix(in srgb, var(--warn) 42%, var(--border));
    background: color-mix(in srgb, var(--warn) 10%, var(--bg-card));
}
.usage-provider.danger {
    color: var(--danger);
    border-color: color-mix(in srgb, var(--danger) 44%, var(--border));
    background: color-mix(in srgb, var(--danger) 10%, var(--bg-card));
}
.usage-body {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.usage-meter {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.usage-meter-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    font-size: 12px;
}
.usage-pct {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.usage-pct.ok { color: var(--ok); }
.usage-pct.warn { color: var(--warn); }
.usage-pct.danger { color: var(--danger); }
.usage-track {
    height: 8px;
    overflow: hidden;
    border-radius: var(--radius-hairline);
    background: var(--bg);
    border: 1px solid color-mix(in srgb, var(--border) 72%, transparent);
}
.usage-fill {
    height: 100%;
    border-radius: inherit;
}
.usage-fill.ok { background: var(--ok); }
.usage-fill.warn { background: var(--warn); }
.usage-fill.danger { background: var(--danger); }
.usage-reset {
    color: var(--text-dim);
    font-size: 11px;
}
.usage-meta {
    padding-top: 10px;
    border-top: 1px solid var(--border);
    font-size: 12px;
}
.usage-summary {
    margin: 0;
    color: var(--text-dim);
    font-size: 12px;
}
.usage-empty { margin: 0; }
.usage-stat-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
}
.usage-stat-grid div {
    min-width: 0;
    padding: 8px 10px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--bg);
}
.usage-stat-grid span {
    display: block;
    color: var(--text-dim);
    font-size: 11px;
    line-height: 1.3;
}
.usage-stat-grid strong {
    display: block;
    margin-top: 3px;
    color: var(--text);
    font-size: 13px;
    font-weight: 650;
    line-height: 1.35;
    overflow-wrap: anywhere;
}

/* ── Auth card (login/setup/password) ────────────────────────────── */

.auth-card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 32px;
    max-width: 420px;
    margin: 80px auto;
    box-shadow: var(--shadow);
}
.auth-card.narrow { margin: 0; }
.auth-card h1 { margin: 0 0 16px; font-size: 20px; }
.auth-card p.dim { color: var(--text-dim); margin: 0 0 24px; font-size: 13px; }

label {
    display: block;
    margin-bottom: 16px;
    font-size: 13px;
    color: var(--text-dim);
}

/* v0.69.1 — 모든 text-like input + textarea + select 의 공통 baseline.
   label 안 / 밖 / form 외부 어디에 있어도 일관된 sizing + 색상. */
input[type=text],
input[type=password],
input[type=number],
input[type=email],
input[type=url],
input[type=search],
input[type=tel],
input[type=date],
input[type=datetime-local],
input[type=time],
input:not([type]),
textarea,
select {
    display: block;
    width: 100%;
    padding: 10px 12px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    font: inherit;
    line-height: 1.4;
    box-sizing: border-box;
}
label input,
label textarea,
label select { margin-top: 6px; }

textarea {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 13px;
    min-height: 80px;
    resize: vertical;
}

input:focus,
textarea:focus,
select:focus { outline: none; border-color: var(--primary); }

input::placeholder,
textarea::placeholder { color: var(--text-dim); opacity: 0.6; }

input[type=checkbox],
input[type=radio] {
    display: inline-block;
    width: auto;
    margin-right: 6px;
    vertical-align: middle;
    accent-color: var(--primary);
}

input[type=file] {
    display: block;
    width: 100%;
    padding: 8px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    font: inherit;
    font-size: 13px;
}
input[type=file]::file-selector-button {
    background: var(--bg-card);
    border: 1px solid var(--border);
    color: var(--text);
    padding: 6px 12px;
    border-radius: var(--radius);
    margin-right: 12px;
    cursor: pointer;
    font: inherit;
    font-size: 13px;
}
input[type=file]::file-selector-button:hover { background: var(--border); }

input[disabled],
textarea[disabled],
select[disabled],
button[disabled],
button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

select {
    appearance: none;
    -webkit-appearance: none;
    background-image: linear-gradient(45deg, transparent 50%, var(--text-dim) 50%),
                      linear-gradient(135deg, var(--text-dim) 50%, transparent 50%);
    background-position: calc(100% - 18px) 50%, calc(100% - 13px) 50%;
    background-size: 5px 5px;
    background-repeat: no-repeat;
    padding-right: 32px;
    cursor: pointer;
}

button {
    cursor: pointer;
    font: inherit;
}
/* 평범한 <button> (variant 미지정) 의 baseline — chip 보다는 형태가 분명한 secondary 버튼. */
button:not(.primary):not(.danger):not(.chip):not(.logout):not(.tab):not(.mobile-nav-toggle):not(.mobile-nav-backdrop) {
    background: var(--bg-card);
    color: var(--text);
    border: 1px solid var(--border);
    padding: 8px 16px;
    border-radius: var(--radius);
    font-weight: 500;
    transition: background 0.1s, border-color 0.1s;
}
button:not(.primary):not(.danger):not(.chip):not(.logout):not(.tab):not(.mobile-nav-toggle):not(.mobile-nav-backdrop):hover {
    background: var(--border);
    border-color: var(--text-dim);
}

button.primary, .primary-link, input[type=submit] {
    background: var(--primary);
    color: white;
    border: none;
    padding: 10px 16px;
    border-radius: var(--radius);
    font-weight: 600;
    width: 100%;
    margin-top: 8px;
    cursor: pointer;
    font: inherit;
}
button.primary:hover, .primary-link:hover, input[type=submit]:hover {
    background: var(--primary-hover); text-decoration: none; color: white;
}

button.danger {
    background: transparent;
    color: var(--danger);
    border: 1px solid var(--danger);
    padding: 4px 10px;
    border-radius: var(--radius);
}
button.danger:hover { background: var(--danger); color: white; }

/* v0.69.1 — Focus visible (접근성). 키보드 사용자에게 명확. */
button:focus-visible,
a:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* ── Banners ─────────────────────────────────────────────────────── */

.error {
    background: rgba(255, 107, 107, 0.1);
    border: 1px solid var(--danger);
    color: var(--danger);
    padding: 10px 14px;
    border-radius: var(--radius);
    margin-bottom: 16px;
    font-size: 13px;
}
.ok-banner {
    background: rgba(105, 219, 124, 0.1);
    border: 1px solid var(--ok);
    color: var(--ok);
    padding: 10px 14px;
    border-radius: var(--radius);
    margin-bottom: 16px;
    font-size: 13px;
}

.hint { color: var(--text-dim); font-size: 12px; margin-top: 8px; }
.dim  { color: var(--text-dim); }
.ok   { color: var(--ok); }
.warn { color: var(--warn); }
code  { background: var(--bg); padding: 2px 6px; border-radius: 3px; font-size: 12px; }

/* v0.69.1 — info / warn banner (기존 .error / .ok-banner 와 짝). */
.warn-banner {
    background: rgba(255, 169, 77, 0.1);
    border: 1px solid var(--warn);
    color: var(--warn);
    padding: 10px 14px;
    border-radius: var(--radius);
    margin-bottom: 16px;
    font-size: 13px;
}
.info-banner {
    background: rgba(94, 158, 255, 0.1);
    border: 1px solid var(--primary);
    color: var(--primary);
    padding: 10px 14px;
    border-radius: var(--radius);
    margin-bottom: 16px;
    font-size: 13px;
}

/* v0.69.1 — generic fieldset (settings-form 외에도 form 들이 fieldset 사용). */
fieldset {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px 18px;
    margin: 0 0 16px;
    background: var(--bg-card);
    min-width: 0; /* flex/grid 안 fieldset 의 overflow 방지 */
}
legend {
    padding: 0 8px;
    font-weight: 600;
    color: var(--text-dim);
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

/* v0.69.1 — generic table (table.devices 외에도 table 들이 데이터 list 표시). */
table {
    width: 100%;
    border-collapse: collapse;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    margin: 0 0 16px;
    font-size: 13px;
}
table th, table td {
    padding: 10px 14px;
    text-align: left;
    border-bottom: 1px solid var(--border);
    vertical-align: top;
    word-break: break-word;
}
table th {
    background: var(--bg-elev);
    color: var(--text-dim);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-size: 11px;
    white-space: nowrap;
}
table tr:last-child td { border-bottom: none; }
table a { color: var(--text); }
table a:hover { color: var(--primary); }
/* 좁은 화면 (모바일) — 표가 화면 밖으로 안 넘치게 horizontal scroll wrapper 권장.
   wrapper 가 없으면 자체적으로 word-break 으로 줄바꿈. */
.table-wrap { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ── Settings form ───────────────────────────────────────────────── */

.settings-form fieldset {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 16px 20px;
    margin-bottom: 16px;
    background: var(--bg-card);
}
.settings-form legend {
    padding: 0 8px;
    font-weight: 600;
    color: var(--text-dim);
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.settings-form button.primary { width: auto; padding: 10px 24px; }

/* ── Devices table ───────────────────────────────────────────────── */

table.devices {
    width: 100%;
    border-collapse: collapse;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
}
table.devices th,
table.devices td {
    padding: 10px 14px;
    text-align: left;
    border-bottom: 1px solid var(--border);
    font-size: 13px;
}
table.devices th {
    background: var(--bg-elev);
    color: var(--text-dim);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-size: 11px;
}
table.devices tr:last-child td { border-bottom: none; }

table.devices a { color: var(--text); text-decoration: none; }
table.devices a:hover { color: var(--primary); }
table.devices a strong { font-weight: 600; }
table.devices small.dim { font-size: 11px; }

/* ── 콘솔 (project console) ──────────────────────────────────────── */

/* v1.6.4 — 콘솔 스크롤 + 우하단 jump-to-bottom 버튼 wrapper. */
.console-log-wrap {
    position: relative;
    /* v1.111.1 — 상단 헤더와 콘솔 박스가 0px 로 붙던 문제. 하단(콘솔↔버튼) 여백과 동일하게
       맞춘다 = 콘솔 margin-bottom(2px) + 하단 바 padding-top(2px) = 4px(사용자 요청). */
    margin-top: 4px;
    /* v1.108.3 — 콘솔 본문과 하단 바(응답중/필터/자동스크롤) 사이 여백 축소(사용자 요청). */
    margin-bottom: 2px;
}

/* v1.161.0 — iframe(embed) 콘솔 레이아웃 회수(모바일/태블릿 소프트키보드).
   iframe 안에서는 window.visualViewport 가 iframe 의 실제 렌더 높이가 아니라 "키보드에
   가려지지 않고 실제로 보이는 부분"을 반영한다. 그래서 콘솔이 자체 계산한
   --app-viewport-height 가 iframe 실제 높이보다 작아지는 경우(태블릿 가로에서 iframe
   하단이 키보드에 가릴 때)가 있고, 그러면 .layout 이 iframe 보다 작아져 하단 공백 +
   내부 압축(콘솔 로그와 입력창이 세로로 겹쳐 입력 글자가 로그에 가려짐)이 발생했다.
   부모 ProjectTabs shell(project-tabs.js)이 이미 iframe 크기를 키보드에 맞춰 관리하므로,
   embed 문서는 자체 뷰포트 계산 대신 iframe 실제 높이(100%)를 그대로 채운다. */
body.pt-embed .layout { height: 100%; }
/* v1.161.0 — 콘솔 .layout 은 grid 라 암묵 row 가 콘텐츠 높이(max-content)로 잡히면,
   콘텐츠가 뷰포트보다 작을 때 .content 가 layout 전체를 못 채워 입력창 아래에 공백이
   남았다. row 를 컨테이너 높이만큼 명시 stretch(minmax(0,1fr)) → .content 가 full
   height → console-log(flex:1)가 남는 세로를 흡수하고 입력창/하단 바가 바닥에 붙는다. */
body.console-page .layout { grid-template-rows: minmax(0, 1fr); }

body.console-page .content {
    display: flex;
    flex-direction: column;
}

body.console-page .console-log-wrap {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.console-log {
    background: var(--console-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    /* v1.70.1 — top padding 제거: sticky 프롬프트(top:0)가 최상단까지 올라가 그 위로
       스크롤 내용이 비치던 문제 해소. 좌우/하단 여백만 유지. */
    padding: 0 14px 12px;
    min-height: 320px;
    max-height: 60vh;
    overflow-y: auto;
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    font-size: 12.5px;
    line-height: 1.55;
    margin-bottom: 0;
    /* v1.6.4 — 명시 scrollbar. firefox + chromium. */
    scrollbar-width: thin;
    scrollbar-color: var(--console-scroll-thumb) transparent;
}

body.console-page .console-log {
    flex: 1 1 auto;
    min-height: 180px;
    max-height: none;
}

.console-tui-shell {
    margin: 10px 0;
    border: 1px solid #242936;
    border-radius: 8px;
    background: #080a0f;
    overflow: hidden;
    will-change: transform;
}
.console-tui-pane {
    height: 420px;
    background: #000;
    position: relative;
    overflow: hidden;
}
.console-tui-terminal-frame {
    height: 100%;
    padding: 8px 8px 28px;
    box-sizing: border-box;
    touch-action: pan-y;
    overflow: hidden;
}
.console-tui-terminal {
    height: 100%;
    min-height: 0;
    overflow: hidden;
}
.console-log::-webkit-scrollbar { width: 10px; }
.console-log::-webkit-scrollbar-track { background: transparent; }
.console-log::-webkit-scrollbar-thumb {
    background: var(--console-scroll-thumb);
    border-radius: var(--radius-scroll-thumb);
    border: 2px solid var(--console-bg);
}
.console-log::-webkit-scrollbar-thumb:hover { background: var(--console-scroll-thumb-hover); }

/* v1.6.4 — 최하단 아닌 경우 표시되는 fly-down 버튼. console-log-wrap 안 absolute. */
.console-jump-bottom {
    position: absolute;
    right: 14px;
    bottom: 14px;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--bg-card);
    border: 1px solid var(--border);
    color: var(--text);
    cursor: pointer;
    display: none;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    line-height: 1;
    padding: 0;
    box-shadow: var(--shadow-floating-control);
    transition: opacity 0.15s ease, transform 0.12s ease;
    opacity: 0.92;
    z-index: 5;
}
.console-jump-bottom:hover { background: var(--primary); color: white; opacity: 1; transform: translateY(-1px); }
.console-jump-bottom.visible { display: flex; }
.console-jump-bottom .badge {
    position: absolute;
    top: -4px; right: -4px;
    background: var(--primary);
    color: white;
    font-size: 10px;
    font-weight: 700;
    border-radius: var(--radius-badge);
    padding: 1px 5px;
    min-width: 16px;
    line-height: 1.2;
    text-align: center;
}

.console-tui-jump-bottom {
    position: absolute;
    right: 16px;
    bottom: var(--console-tui-jump-bottom-offset, 72px);
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 1px solid var(--border);
    background: var(--bg-card);
    color: var(--text);
    cursor: pointer;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 0;
    font-size: 24px;
    line-height: 1;
    opacity: 0.6;
    box-shadow: var(--shadow-floating-control);
    z-index: 6;
    transition: opacity 0.15s ease, transform 0.12s ease, background 0.15s ease, color 0.15s ease;
}
.console-tui-jump-bottom.visible { display: flex; }
.console-tui-jump-bottom:hover,
.console-tui-jump-bottom:focus-visible {
    background: var(--primary);
    color: white;
    opacity: 0.9;
    transform: translateY(-1px);
}
@media (prefers-reduced-motion: reduce) {
    .console-tui-jump-bottom { transition: none; }
}
@media (max-width: 620px) {
    .console-tui-jump-bottom {
        right: 12px;
        bottom: var(--console-tui-jump-bottom-offset-mobile, 84px);
    }
}

.console-tui-actions {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.console-tui-action {
    width: 28px;
    height: 26px;
    border-radius: 6px;
    border: 1px solid var(--border);
    background: rgba(255,255,255,0.04);
    color: var(--text-dim);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
}
.console-tui-action:hover,
.console-tui-action:focus-visible,
.console-tui-action.active {
    color: var(--text);
    border-color: var(--primary);
    background: rgba(51,154,240,0.12);
}
.console-tui-action.copied {
    color: var(--ok, #69db7c);
    border-color: rgba(105,219,124,0.5);
    background: rgba(105,219,124,0.12);
}
.console-tui-action:disabled {
    opacity: 0.38;
    cursor: default;
    border-color: var(--border);
    background: rgba(255,255,255,0.025);
}
.console-tui-search {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 7;
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 6px;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: rgba(8, 10, 15, 0.96);
    box-shadow: var(--shadow-floating-control);
}
.console-tui-search[hidden] {
    display: none;
}
.console-tui-search input[type=search] {
    width: min(260px, 46vw);
    height: 28px;
    padding: 4px 8px;
    border-radius: 6px;
    border: 1px solid var(--border);
    background: #05070b;
    color: var(--text);
    font-size: 12px;
}
.console-tui-search input[type=search]:focus {
    outline: none;
    border-color: var(--primary);
}
@media (max-width: 620px) {
    .console-tui-search {
        left: 8px;
        right: 8px;
        top: 8px;
    }
    .console-tui-search input[type=search] {
        flex: 1;
        width: auto;
        min-width: 0;
    }
}

/* v1.21.0 — Claude Code 터미널 스타일에 가깝게 재구성.
   - 90px label column 제거 → 단일 column + 짧은 ASCII prefix (::before pseudo).
   - 카드 사이 border 제거, padding tight (dense terminal feel).
   - role 별 색상 prefix 만 색 — 본문은 모노스페이스 흰색. */
/* v1.86.0 — 채팅 버블 레이아웃. 각 메시지를 말풍선으로 감싼다.
   user=우측 강조 / assistant=좌측 중립(마크다운) / tool=좌측 인셋 /
   sys=중앙 pill / thinking·뱃지=좌측 흐린 작은 버블. */
.console-log .log-line {
    display: flex;
    margin: 6px 0;
    align-items: flex-start;
    border-bottom: none;
}
.console-log .log-line::before { display: none; }
.console-log .log-label { display: none; }
.console-log .log-content {
    display: flex; flex-direction: column; min-width: 0;
    max-width: 82%;
    padding: 7px 12px;
    border-radius: var(--radius-console-bubble);
    background: var(--console-bubble-fill);
    border: 1px solid var(--console-bubble-fill);
}
.console-log .log-body { white-space: pre-wrap; word-break: break-word; }

/* v1.86.1 — 내 프롬프트는 버블 대신 과거 sticky 상단고정 + 터미널('> ') 스타일 유지.
   버블 우측정렬(flex-end)이 .log-line.user 의 position:sticky 와 충돌해 UI 가 깨졌다. */
.console-log .log-line.user { display: block; }
.console-log .log-line.user::before {
    display: inline; position: absolute;
    content: '> '; color: var(--primary);
    font-weight: 600; white-space: pre; user-select: none;
}
.console-log .user .log-content {
    background: none; border: none; padding: 0;
    max-width: 100%; border-radius: 0;
}
/* claude 응답 — 좌측 중립 버블 (마크다운 렌더) */
.console-log .assistant .log-content {
    background: var(--console-assistant-fill);
    border-color: var(--console-assistant-border);
    border-bottom-left-radius: 4px;
}
/* 도구 호출/결과 — 좌측 인셋, 작은 모노 버블 */
.console-log .tool .log-content {
    background: var(--console-tool-fill);
    border-color: var(--console-tool-border);
    font-size: 0.92em; max-width: 90%;
}
.console-log .tool-out .log-content {
    background: var(--console-tool-out-fill);
    border-color: var(--console-tool-out-border);
    font-size: 0.92em; max-width: 90%;
}
.console-log .tool-err .log-content,
.console-log .err .log-content {
    background: var(--console-error-fill);
    border-color: var(--console-error-border);
}
/* 시스템/완료/replay — 좌측 작은 pill (v1.86.2 — 모든 응답 버블 좌측 정렬) */
.console-log .sys { justify-content: flex-start; }
.console-log .sys .log-content {
    background: var(--console-sys-fill);
    border: none;
    font-size: 0.82em;
    padding: 3px 11px;
    border-radius: var(--radius-console-pill);
    color: var(--console-sys-text);
    max-width: 90%;
    text-align: center;
}
/* thinking / 파싱 불가 — 좌측 흐린 작은 뱃지(이름만) */
.console-log .thinking { justify-content: flex-start; }
.console-log .thinking .log-content {
    background: var(--console-thinking-fill);
    border-color: var(--console-thinking-border);
    font-style: italic;
    opacity: 0.85;
    font-size: 0.88em;
    padding: 4px 10px;
    border-radius: var(--radius-console-pill);
}

/* v1.7.9 — 응답 카드 내부 하단 meta: 시각 + 복사 버튼. 우측 정렬. */
.console-log .log-meta {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 8px;
    margin-top: 2px;
    opacity: 0.45;
    transition: opacity 0.15s;
}
.console-log .log-line:hover .log-meta { opacity: 1; }
.console-log .log-time {
    color: var(--text-dim);
    font-size: 10.5px;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    user-select: none;
}
.console-log .log-copy {
    background: transparent;
    border: none;
    color: var(--text-dim);
    cursor: pointer;
    padding: 0;
    line-height: 0;
    transition: color 0.15s;
}
.console-log .log-copy:hover { color: var(--text); }
.console-log .log-copy.copied { color: var(--console-assistant-accent); }
/* v1.70.2 → v1.70.3 — 복사 아이콘 축소 (14 → 9px, 원본의 ~2/3). */
.console-log .log-copy svg { display: block; width: 9px; height: 9px; }

/* v1.7.12 — 응답중 spinner. console-log 직후 위치, busy 일 때만 visible. */
.console-spinner {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-top: 1px solid rgba(255,255,255,0.05);
    color: var(--text-dim);
    font-size: 12px;
    user-select: none;
}
.console-spinner[hidden] { display: none; }
.console-spinner .spinner {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    border: 2px solid rgba(105,219,124,0.25);
    border-top-color: #69db7c;
    animation: vibe-spinner-rotate 0.85s linear infinite;
    flex-shrink: 0;
}
.console-spinner .spinner-label { color: #69db7c; font-weight: 500; }
@keyframes vibe-spinner-rotate {
    to { transform: rotate(360deg); }
}
/* v1.108.2 — 콘솔 하단 바: 좌측 응답중 스피너(busy 때만) + 우측 정렬 필터/자동스크롤 토글.
   필터/자동스크롤을 상단에서 콘솔 하단(응답중과 같은 줄)으로 이동(사용자 요청). */
.console-bottom-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    /* v1.108.3 — 콘솔 본문에 바짝 붙도록 상단 패딩 축소(사용자 요청). */
    padding: 2px 2px 0;
    min-height: 26px;
    margin-bottom: 10px;
    /* v1.110.0 — 세션/모델/MCP 가 하단 바로 이동해 폭이 커졌으므로 좁은 폭에서 줄바꿈 허용. */
    flex-wrap: wrap;
}
.console-bottom-tools { flex-wrap: wrap; }
.console-bottom-bar .console-spinner {
    padding: 0;          /* 패딩/구분선은 바가 담당 — 스피너는 inline 으로만 */
    border-top: none;
}
.console-bottom-tools {
    margin-left: auto;   /* 스피너가 hidden 이어도 항상 우측 정렬 유지 */
    display: flex;
    align-items: center;
    gap: 8px;
}
/* v1.62.0 — MCP 카드 인라인 설치 스피너 (키프레임 재사용). */
.mcp-spinner {
    display: inline-block;
    width: 13px;
    height: 13px;
    border-radius: 50%;
    border: 2px solid rgba(105,219,124,0.25);
    border-top-color: #69db7c;
    animation: vibe-spinner-rotate 0.85s linear infinite;
    flex-shrink: 0;
}

.console-log .sys .log-label   { color: #6c7a93; }
.console-log .user .log-label  { color: var(--primary); }
.console-log .user .log-body   { color: var(--text); }

/* v1.59.2 → v1.70.1 — 내가 보낸 프롬프트 카드를 스크롤 상단에 고정(sticky).
   지금 응답이 어떤 프롬프트에 대한 것인지 한눈에 보인다. sticky 형제 특성상 다음
   user 카드가 올라오면 이전 카드를 교체(겹치지 않음) → 항상 "직전 프롬프트" 1장 고정.
   v1.70.1:
   - 불투명 파랑 틴트 배경 + 좌측 강조선(inset shadow) 으로 응답/시스템 카드와 구분.
     불투명이라 고정 시 아래 내용이 비치지 않는다.
   - 긴 프롬프트는 앞 2줄만 표시(line-clamp) — 콘솔 전체를 덮지 않음. 카드 클릭으로
     펼침/접힘(.expanded). */
.console-log .log-line.user {
    background: var(--console-sticky-bg);
    box-shadow: inset 3px 0 0 var(--primary),
                0 8px 12px -10px rgba(0,0,0,0.75);
    margin: 0 -14px;            /* console-log 좌우 padding 만큼 넓혀 가장자리까지 덮음 */
    padding-top: 3px;
    padding-bottom: 3px;
    padding-left: calc(1.6em + 14px);
    padding-right: 14px;
    cursor: pointer;
}
/* v1.104.1 — 상단 고정은 "가장 최신" 프롬프트(.cur)만. 이전엔 모든 .user 가 sticky 라,
   마지막 프롬프트의 응답이 짧아 아직 top:0 까지 안 밀려 올라가면 그 위의 이전 프롬프트가
   top:0 에 stacking 고정돼 "최신이 아닌 이전 프롬프트가 상단에 붙는" 문제가 있었다.
   JS(append)가 새 user 메시지마다 .cur 를 최신 1개에만 부여한다. */
.console-log .log-line.user.cur {
    position: sticky;
    top: 0;
    z-index: 3;
}
.console-log .log-line.user::before { left: 14px; top: 3px; }  /* margin/padding 보정 */
/* 기본: 앞 2줄만. 클릭 시 .expanded 로 전체(최대 40vh, 자체 스크롤). */
.console-log .log-line.user .log-body {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.console-log .log-line.user.expanded .log-body {
    display: block;
    max-height: 40vh;
    overflow-y: auto;
    overscroll-behavior: contain;
}
.console-log .assistant .log-label { color: var(--console-assistant-accent); }
.console-log .tool .log-label  { color: var(--console-tool-accent); }
.console-log .tool-out .log-label { color: var(--console-tool-out-accent); }
.console-log .tool-err .log-label { color: var(--danger); }
.console-log .tool-err .log-body  { color: var(--danger); }
.console-log .err .log-label   { color: var(--danger); }
.console-log .err .log-body    { color: var(--danger); }

.prompt-form textarea {
    width: 100%;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    padding: 10px 12px;
    font: inherit;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 13px;
    resize: vertical;
}
.prompt-form textarea:focus { outline: none; border-color: var(--primary); }

@media (max-height: 760px), (max-width: 900px) {
    body.console-keyboard .content {
        padding-top: 8px;
        padding-bottom: 8px;
    }
    /* v1.161.1 — 키보드로 세로가 좁아지면 console-log 의 min-height(72px)가 flex 축소를
       막아, console-log-wrap 이 압축돼도 console-log 가 wrap 밖으로 넘쳐 아래 입력창(textarea)
       을 덮던 겹침(모바일/태블릿 "텍스트창이 콘솔 뒤로 가려짐")을 회수. min-height:0 으로
       console-log 가 남는 세로만큼만 차지(내부 스크롤)하게 하고, wrap overflow:hidden 으로
       넘침을 이중 차단. 압축 흡수는 여전히 console-log-wrap(flex:1, min-height:0)이 담당. */
    body.console-keyboard .console-log {
        min-height: 0;
    }
    body.console-keyboard .console-log-wrap {
        overflow: hidden;
    }
    /* v1.161.2 — max-height 제약 제거: 부모 row(align-items:stretch) 의 우측 버튼 컬럼
       (voice/image/interrupt/send)이 이미 입력 row 높이를 지배하므로, textarea 를 그 높이
       (=전송 버튼 하단)까지 stretch 시켜도 로그 공간을 추가로 잠식하지 않는다(오히려 textarea
       아래 낭비 공간 회수). v1.161.1 의 max-height:64px 가 textarea 를 버튼 2개(마이크+이미지)
       높이에 clamp 해 "입력창이 반토막" 나던 문제를 회수. min-height 는 버튼 컬럼이 예외적으로
       작을 때의 하한. */
    body.console-keyboard .prompt-form textarea {
        min-height: 44px;
        max-height: none;
        resize: none;
    }
    /* v1.161.1 — 키보드 모드에선 입력창 아래 힌트 줄(전송/줄바꿈 안내)을 접어 로그 가시 공간 확보. */
    body.console-keyboard #prompt-form > div:last-child {
        display: none;
    }
    body.console-keyboard #quick-prompts {
        display: flex !important;
        flex-wrap: nowrap;
        gap: 4px;
        margin: 4px 0;
        /* v1.158.10 — .content 가 flex column + 고정 height(--app-viewport-height) 이고
           overflow-y:hidden 이라 flex automatic minimum size 가 0 이 되면서, 키보드로
           세로가 좁아지면 이 행이 0 높이까지 짓눌려 텍스트가 겹쳤다. shrink 를 막아
           자기 높이를 유지 → 세로 압축은 console-log-wrap(flex:1, min-height:0)만 흡수. */
        flex-shrink: 0;
        overflow-x: auto;
        overflow-y: hidden;
        scrollbar-width: none;
    }
    body.console-keyboard #quick-prompts::-webkit-scrollbar { display: none; }
    body.console-keyboard #quick-prompts .qp-btn {
        padding: 4px 9px;
        font-size: 11px;
        flex: 0 0 auto;
    }
    body.console-keyboard #quick-prompts .qp-sep {
        flex: 0 0 auto;
        min-height: 18px;
    }
    body.console-keyboard .console-template-row,
    body.console-keyboard .console-agent-row {
        display: flex !important;
        flex-wrap: nowrap !important;
        gap: 4px !important;
        margin-top: 4px !important;
        /* v1.158.10 — 위 #quick-prompts 와 동일: flex column 세로 압축 시 짓눌림 방지. */
        flex-shrink: 0 !important;
        overflow-x: auto;
        overflow-y: hidden;
        scrollbar-width: none;
    }
    body.console-keyboard .console-template-row::-webkit-scrollbar,
    body.console-keyboard .console-agent-row::-webkit-scrollbar { display: none; }
    body.console-keyboard .console-template-row select,
    body.console-keyboard .console-agent-row select {
        min-width: 120px !important;
        min-height: 32px;
    }
    body.console-keyboard .console-template-row .chip,
    body.console-keyboard .console-agent-row .chip {
        padding: 5px 9px;
        white-space: nowrap;
    }
    body.console-keyboard .console-bottom-bar {
        display: flex !important;
        gap: 4px;
        min-height: 24px;
        margin-top: 4px !important;
        margin-bottom: 0;
        padding: 0 2px;
        /* v1.158.10 — flex column 세로 압축 시 짓눌림 방지. */
        flex-shrink: 0;
        overflow-x: auto;
        overflow-y: hidden;
        scrollbar-width: none;
    }
    body.console-keyboard .console-bottom-bar::-webkit-scrollbar { display: none; }
    body.console-keyboard .console-bottom-tools {
        gap: 4px;
        margin-left: 0;
        flex-wrap: nowrap;
    }
}

/* ── Chip 버튼 (콘솔 액션, 페이지간 이동) ────────────────────────── */

.chip {
    display: inline-block;
    padding: 4px 10px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--bg);
    color: var(--text-dim);
    font: inherit;
    font-size: 12px;
    line-height: 1.6;
    cursor: pointer;
    text-decoration: none;
    transition: background 0.1s, color 0.1s, border-color 0.1s;
}
.chip:hover {
    background: var(--bg-card);
    color: var(--text);
    border-color: var(--text-dim);
    text-decoration: none;
}
.chip-link { color: var(--text-dim); }
/* v1.76.0 — 일관된 뒤로가기 아이콘 버튼(프로젝트/설정 sub-page 복귀). AdminTemplates.backButton. */
.back-btn {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 6px 12px; border-radius: 8px;
    background: var(--bg-card); border: 1px solid var(--border);
    color: var(--text-dim); text-decoration: none; font-size: 13px; line-height: 1;
    transition: background .15s, color .15s, border-color .15s;
}
.back-btn:hover { background: var(--bg-elev); color: var(--text); border-color: var(--primary); }
.back-btn svg { flex-shrink: 0; }

/* v1.78.0 — 대시보드 서버 상태 원형 게이지(#sys-card). r=15.915 둘레≈100 → dasharray 백분율. */
#sys-card .gauges {
    display: flex; gap: 16px; flex-wrap: wrap;
    justify-content: space-around; margin: 8px 0 16px;
}
#sys-card .gauge-box { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.gauge { width: 84px; height: 84px; }
.gauge-track { fill: none; stroke: var(--border); stroke-width: 3.2; }
/* v1.79.0 — 2색 도넛: 파랑=서버 전체(total), 초록=vibe-coder 점유(vibe, total 위에 겹쳐 그림). */
.gauge-total {
    fill: none; stroke: var(--primary); stroke-width: 3.2; stroke-linecap: round;
}
.gauge-vibe {
    fill: none; stroke: var(--console-gauge-vibe); stroke-width: 3.2; stroke-linecap: round;
}
.gauge-txt { fill: var(--text); font-size: 9px; font-weight: 600; text-anchor: middle; dominant-baseline: central; }
#sys-card .gauge-label { font-size: 12px; color: var(--text-dim); }
#sys-card .gauge-legend {
    display: flex; gap: 16px; justify-content: center;
    font-size: 12px; color: var(--text-dim); margin: 2px 0 12px;
}
#sys-card .gauge-legend .lg::before {
    content: ''; display: inline-block; width: 9px; height: 9px;
    border-radius: 2px; margin-right: 5px; vertical-align: middle;
}
#sys-card .lg-total::before { background: var(--primary); }
#sys-card .lg-vibe::before { background: var(--console-gauge-vibe); }
#sys-card .sys-detail { margin: 0; }
.chip-danger {
    border-color: var(--danger);
    color: var(--danger);
}
.chip-danger:hover {
    background: var(--danger);
    color: white;
    border-color: var(--danger);
}

/* ── 프로젝트 목록 상태칩 (v1.53.0) ─────────────────────────────────
   응답중(responding) / 대기중(ready) / 유휴(idle) 시각화. 좌측 점 +
   pill 배경. responding 은 pulse 애니메이션으로 진행 중임을 강조. */
.pstat {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 9px;
    border-radius: 999px;
    border: 1px solid var(--border);
    font-size: 12px;
    line-height: 1.5;
    white-space: nowrap;
}
.pstat::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: currentColor;
    flex: none;
}
/* v1.100.0 — 5-state 일관: 응답중=초록(콘솔 뱃지와 동일). 이전엔 주황이었다. */
.pstat-responding {
    color: var(--ok);
    border-color: rgba(105, 219, 124, 0.4);
    background: rgba(105, 219, 124, 0.08);
}
.pstat-responding::before { animation: pstat-pulse 1.2s ease-in-out infinite; }
/* v1.100.0 — 유휴(진행 중 아님)=그레이. ready 는 idle 의 별칭. */
.pstat-ready, .pstat-idle { color: var(--text-dim); }
/* v1.100.0 — 대기중(백그라운드 작업 진행 → turn 재개 대기)=노랑. */
.pstat-waiting {
    color: var(--wait, #fab005);
    border-color: rgba(250, 176, 5, 0.4);
    background: rgba(250, 176, 5, 0.08);
}
/* v1.60.0 → v1.100.0 — 중단됨(cancel/crash/idle/rate-limit 소진)=보라. 이전엔 빨강. */
.pstat-stopped {
    color: var(--halt, #b197fc);
    border-color: var(--status-stopped-border);
    background: var(--status-stopped-fill);
}
/* v1.100.0 — 에러(API/turn 에러 종료)=빨강. */
.pstat-error {
    color: var(--danger, #ff6b6b);
    border-color: rgba(255, 107, 107, 0.4);
    background: rgba(255, 107, 107, 0.08);
}
/* v1.100.0 — MCP 카드 pill 은 pstat 색 팔레트를 빌려쓰되 의미가 다르다(설치 상태,
   turn 상태 아님). ready=설치됨 은 긍정이므로 초록을 유지 — 일반 ready(유휴, 그레이)
   로 바뀐 영향에서 분리. notInstalled=idle 은 그레이 그대로 적절. */
.mcp-pill.pstat-ready {
    color: var(--ok);
    border-color: rgba(105, 219, 124, 0.4);
    background: rgba(105, 219, 124, 0.08);
}
@keyframes pstat-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.25; }
}
@media (prefers-reduced-motion: reduce) {
    .pstat-responding::before { animation: none; }
}

/* Provider status dots: Claude / Codex / GLM. Used in project lists and switchers. */
.agent-status-dots {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    min-width: 43px;
    padding: 4px 7px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: rgba(15, 20, 25, 0.72);
    vertical-align: middle;
}
.agent-dot {
    width: 8px;
    height: 8px;
    border-radius: 999px;
    flex: none;
    background: var(--text-dim);
    opacity: 0.72;
    box-shadow: 0 0 0 1px rgba(255,255,255,0.08);
}
.agent-dot[data-state="ready"],
.agent-dot[data-state="idle"],
.agent-dot[data-state="completed"],
.agent-dot[data-state="disconnected"] {
    background: var(--text-dim);
}
.agent-dot[data-state="responding"],
.agent-dot[data-state="running"] {
    background: var(--ok, #69db7c);
    opacity: 1;
    animation: pstat-pulse 1.2s ease-in-out infinite;
}
.agent-dot[data-state="waiting"],
.agent-dot[data-state="waiting_input"],
.agent-dot[data-state="waiting_approval"] {
    background: var(--halt, #b197fc);
    opacity: 1;
}
.agent-dot[data-state="starting"] {
    background: var(--wait, #fab005);
    opacity: 1;
}
.agent-dot[data-state="stopped"],
.agent-dot[data-state="interrupted"] {
    background: var(--halt, #b197fc);
    opacity: 0.86;
}
.agent-dot[data-state="error"] {
    background: var(--danger, #ff6b6b);
    opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
    .agent-dot[data-state="responding"],
    .agent-dot[data-state="running"] { animation: none; }
}

/* ── 설치 진행 progress bar ─────────────────────────────────────── */

.progress-bar {
    width: 100%;
    height: 8px;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 999px;
    overflow: hidden;
}
.progress-fill {
    height: 100%;
    width: 0%;
    background: var(--primary);
    transition: background 0.2s;
}
.progress-fill.done-ok   { background: var(--ok); }
.progress-fill.done-fail { background: var(--danger); }

/* ── git diff 블록 ───────────────────────────────────────────────── */

pre.diff-block {
    background: var(--console-bg);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 10px 12px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 12px;
    line-height: 1.5;
    overflow-x: auto;
    max-height: 60vh;
    margin: 0;
}

/* ── Settings tabs (v0.69.0 → v0.69.1 inline 에서 분리) ───────────── */

.settings-tabs {
    display: flex;
    gap: 4px;
    flex-wrap: wrap;
    border-bottom: 1px solid var(--border);
    margin: -8px -8px 20px -8px;
    padding: 0 8px;
}
.settings-tabs .tab {
    padding: 10px 14px;
    text-decoration: none;
    color: var(--text-dim);
    border-bottom: 2px solid transparent;
    font-size: 14px;
    transition: color 0.1s, border-color 0.1s;
    white-space: nowrap;
}
.settings-tabs .tab:hover { color: var(--text); text-decoration: none; }
.settings-tabs .tab.active {
    color: var(--text);
    border-bottom-color: var(--primary);
    font-weight: 600;
}

/* ── Responsive ──────────────────────────────────────────────────── */

/* Tablet — 좁은 데스크탑 / 가로 태블릿. 사이드바 narrower. */
@media (max-width: 1024px) {
    .layout { grid-template-columns: 180px 1fr; }
    .content { padding: 24px; }
}

/* 작은 태블릿 / 큰 폰. 모바일은 wrap nav 가 아니라 compact app bar + drawer 로 전환.
   nav label 이 길거나 browser zoom 이 켜져도 header 가 여러 줄로 늘어나 content 를
   밀어내지 않는다. */
@media (max-width: 768px) {
    /* v1.33.1 — 1칼럼 + rows(헤더 auto / 컨텐츠 1fr). 이전엔 grid-template-rows 가
       없어 fullbleed 탭(#project-tabs-root height:100%)의 높이 기준이 무너졌음. */
    .layout { grid-template-columns: 1fr; grid-template-rows: auto minmax(0, 1fr); }
    body.mobile-nav-open {
        overflow: hidden;
    }
    .sidebar {
        flex-direction: row;
        align-items: center;
        padding: 8px 12px;
        gap: 10px;
        flex-wrap: nowrap;
        border-right: none;
        border-bottom: 1px solid var(--border);
        min-height: 56px;
        overflow: visible;
    }
    /* v1.33.1 — 가로 헤더에선 접기 토글 불필요, quota pill 은 좁아 부적합. */
    .sidebar-toggle { display: none; }
    .quota-pill { display: none; }
    .mobile-nav-toggle { display: inline-flex; margin-left: auto; }
    /* v1.7.6 — mobile: brand 는 horizontal (icon + title 한 줄). */
    .brand { flex-direction: row; gap: 8px; padding: 0; min-width: 0; }
    .brand-icon { width: 32px; height: 32px; }
    .brand-title {
        min-width: 0;
        max-width: min(46vw, 220px);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .nav-links {
        position: fixed;
        top: 0;
        right: 0;
        bottom: 0;
        z-index: 80;
        width: min(320px, calc(100vw - 44px));
        padding: calc(16px + env(safe-area-inset-top)) 16px calc(16px + env(safe-area-inset-bottom));
        background: var(--bg-elev);
        border-left: 1px solid var(--border);
        box-shadow: var(--shadow-drawer);
        flex-direction: column;
        gap: 6px;
        overflow-y: auto;
        overflow-x: hidden;
        overscroll-behavior: contain;
        pointer-events: none;
        transform: translateX(100%);
        visibility: hidden;
        transition: transform 0.16s ease, visibility 0.16s ease;
    }
    body.mobile-nav-open .nav-links {
        transform: translateX(0);
        visibility: visible;
        pointer-events: auto;
    }
    .nav-links a {
        min-height: 44px;
        min-width: 0;
        padding: 10px 12px;
        font-size: 14px;
        gap: 10px;
    }
    .nav-links a .nav-label { overflow-wrap: anywhere; }
    .nav-links a .nav-icon { width: 20px; height: 20px; }
    .mobile-nav-backdrop {
        position: fixed;
        inset: 0;
        z-index: 70;
        border: 0;
        padding: 0;
        background: var(--overlay-scrim);
        cursor: pointer;
    }
    body.mobile-nav-open .mobile-nav-backdrop { display: block; }
    .user-box { display: none; }
    .content { padding: 20px 16px; }
    .auth-card { margin: 24px auto; max-width: 100%; padding: 24px; }
    .settings-tabs { margin-left: -16px; margin-right: -16px; padding: 0 16px;
                     overflow-x: auto; -webkit-overflow-scrolling: touch; }
    .settings-tabs::-webkit-scrollbar { display: none; }
}

@media (max-width: 768px) and (prefers-reduced-motion: reduce) {
    .nav-links { transition: none; }
}

/* 모바일 폰. fieldset/card padding 줄임. */
@media (max-width: 480px) {
    .content { padding: 16px 12px; }
    .grid { grid-template-columns: 1fr; gap: 12px; }
    .card { padding: 16px; }
    .auth-card { padding: 20px; margin: 16px auto; }
    fieldset { padding: 12px 14px; }
    h1 { font-size: 20px; margin-bottom: 16px; }
    h2 { font-size: 16px; }
    button.primary, .primary-link, input[type=submit] { padding: 12px 16px; font-size: 15px; }
    /* 표 가로 스크롤 fallback — wrapper 가 없는 일반 table 도 깨지지 않게. */
    table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
    table thead, table tbody, table tr { display: table; width: 100%; table-layout: fixed; }
}
