/* ─────────────────────────────────────────────────────────────────────────────
   40-v2.css — 새 1탭 셸(#1719) + 클래식 임베드(?embed=1) 모드.
   토큰은 01-base.css 것만 쓴다(새 색 없음). 채운 파랑은 화면당 하나(주 액션). 상태 = 점 + 글자.
   ⚠ 이 파일은 캐스케이드 맨 뒤다 — 클래식 규칙(특히 35-liv.css 의 body[data-route="liv"] …)을 여기서 되잡는다.
   ───────────────────────────────────────────────────────────────────────────── */

/* ── 임베드 모드: 새 셸이 클래식 화면을 iframe 에 실을 때. 크롬만 걷고 화면 코드는 그대로. ── */
body.embed #org-banner, body.embed #desktop-update, body.embed header.topbar, body.embed footer.app-foot, body.embed #skip-link { display: none !important; }
body.embed #view { padding-top: 12px; }
/* #1841 임베드(액자 안)에서 클래식 상단바(64px)를 전제한 값들을 되돌린다 — 상단바가 없으니 sticky top:64 는 64px 빈칸이 되고,
   main padding-top(32) 상쇄용 margin-top:-32 는 위 12px 패딩보다 커서 빵부스러기 윗줄이 액자 밖으로 잘렸다(실측 crumb top -10 / 사이드바 머리 84). */
body.embed .pjv-listboard.pjv-has-side { margin-top: -12px; }
body.embed .pjv-has-side .pjv-side-nav-inner { top: 0; max-height: 100vh; padding-top: 10px; }
body.embed .pjv-has-side .pjv-side-main { min-height: 100vh; }
body.embed .kn-shell { min-height: 100vh; }
body.embed .kn-side { top: 0; max-height: 100vh; padding-top: 14px; }
/* 액자 띠 없는 앱(FRAMELESS) — 새 탭 열기만 우상단 작은 아이콘으로 남긴다(기능 유지). */
.v2-app-frameless { position: relative; }
.v2-frame-pop { position: absolute; top: 6px; right: 10px; z-index: 2; width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center; border-radius: 6px; color: var(--muted-2); text-decoration: none; font-size: 13px; background: var(--bg); opacity: .7; }
.v2-frame-pop:hover { color: var(--ink); background: var(--bg-tint-2); opacity: 1; }
body.embed .liv-head { display: none; } /* 리브 페이지도 임베드되면 '← 라이블리'가 이중이 된다 */

/* ── 새 셸 켜짐: 클래식 크롬 숨김, 뿌리 전체 화면 ── */
body[data-ui="v2"] { height: 100vh; overflow: hidden; margin: 0; }
body[data-ui="v2"] #app { display: block !important; height: 100vh; }
body[data-ui="v2"] #org-banner, body[data-ui="v2"] #desktop-update, body[data-ui="v2"] header.topbar, body[data-ui="v2"] main#view, body[data-ui="v2"] footer.app-foot, body[data-ui="v2"] #skip-link { display: none !important; }
/* 세 칸 + 사이 손잡이 둘(v2/split.ts) — 너비는 변수, 손잡이가 바꾼다(기억됨). no-aside 면 우패널·그 손잡이는 0. */
#v2-root { --v2-side-w: 292px; --v2-aside-w: 316px; height: 100vh; display: grid; grid-template-columns: var(--v2-side-w) 6px minmax(0, 1fr) 6px var(--v2-aside-w); background: var(--bg); color: var(--ink); }
#v2-root.no-aside { grid-template-columns: var(--v2-side-w) 6px minmax(0, 1fr) 0 0; }
#v2-root.no-aside .v2-aside { display: none; }
#v2-root.no-aside > .v2-split-x + .v2-main + .v2-split-x { display: none; }
/* 팝아웃 창(#1744 ?solo=1) — 세션 하나만 담은 창. **왼쪽 탐색열만 없다**: 가운데·우패널은 본 화면과 같은 부품이라
   여기서는 열 정의만 두 칸으로 줄인다(가운데 판이 창 왼쪽 끝에 붙으므로 그쪽 테두리는 지운다). */
#v2-root.solo { grid-template-columns: minmax(0, 1fr) 6px var(--v2-aside-w); }
#v2-root.solo.no-aside { grid-template-columns: minmax(0, 1fr) 0 0; }
.v2-split { position: relative; z-index: 3; background: transparent; touch-action: none; }
.v2-split-x { cursor: col-resize; }
.v2-split-y { cursor: row-resize; height: 6px; flex: none; }
.v2-split::after { content: ''; position: absolute; background: var(--blue-fill); opacity: 0; transition: opacity .12s; border-radius: 2px; }
.v2-split-x::after { top: 0; bottom: 0; left: 2px; right: 2px; }
.v2-split-y::after { left: 0; right: 0; top: 2px; bottom: 2px; }
.v2-split:hover::after, .v2-split.on::after, .v2-split:focus-visible::after { opacity: .55; }
.v2-split:focus-visible { outline: none; }
body.v2-splitting-x, body.v2-splitting-x * { cursor: col-resize !important; user-select: none; }
body.v2-splitting-y, body.v2-splitting-y * { cursor: row-resize !important; user-select: none; }
body.v2-splitting-x iframe, body.v2-splitting-y iframe { pointer-events: none; }
#v2-root .v2-ic { width: 16px; height: 16px; stroke: currentColor; stroke-width: 1.7; fill: none; stroke-linecap: round; stroke-linejoin: round; flex: none; }
.v2-k { font-family: var(--mono, ui-monospace, monospace); font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.v2-dot { width: 6px; height: 6px; border-radius: 50%; background: transparent; box-shadow: inset 0 0 0 1.5px var(--muted-2); flex: none; display: inline-block; box-sizing: border-box; }
/* 상태점 어휘(web/v2/views.ts dotCls) — 색은 셋뿐: 작업 중·확인 필요·작업 완료. 나머지 살아 있는 것은 회색, 끝난 것은 빈 점(기본). */
.v2-dot.busy { background: var(--blue-fill); box-shadow: none; animation: v2pulse 1.1s ease-in-out infinite; }
.v2-dot.wait { background: var(--warn-deep); box-shadow: 0 0 0 2.5px color-mix(in srgb, var(--warn-deep) 22%, transparent); }
.v2-dot.done { background: var(--mint-deep); box-shadow: 0 0 0 2.5px color-mix(in srgb, var(--mint-deep) 22%, transparent); }
.v2-dot.idle { background: var(--muted-2); box-shadow: none; }
.v2-dot.off { background: transparent; box-shadow: inset 0 0 0 1.5px var(--muted-2); }
.v2-dot.shell { background: var(--muted-head); box-shadow: none; border-radius: 2px; }
@keyframes v2pulse { 50% { opacity: .35; } }
.v2-cnt { font-family: var(--mono, ui-monospace, monospace); font-size: 11px; color: var(--muted-2); }
.v2-muted { color: var(--muted); font-size: 13px; }
.v2-empty { font-size: 12.5px; color: var(--muted); line-height: 1.6; margin: 0; padding: 8px 4px; }
.v2-fine { font-size: 11.5px; color: var(--muted); line-height: 1.6; margin: 10px 0 0; }

.v2-ws { flex: 1; min-width: 0; display: flex; align-items: center; gap: 7px; padding: 6px 8px; border: 1px solid transparent; border-radius: 8px; background: none; font: inherit; text-align: left; cursor: pointer; }
.v2-ws:hover { background: var(--bg); border-color: var(--line); }
.v2-ws-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; font-weight: 700; color: var(--ink); }
.v2-ws-car { font-size: 10px; color: var(--muted-2); flex: none; }
.v2-ws-badge { flex: none; font-family: var(--mono, ui-monospace, monospace); font-size: 10px; letter-spacing: .04em; font-weight: 700; padding: 1px 5px; border-radius: 5px; border: 1px solid transparent; }
.v2-ws-badge.personal { color: var(--mint-deep); background: var(--bg-success); border-color: var(--ok-line-2); }
.v2-ws-badge.team { color: var(--blue); background: var(--bg-tint); border-color: var(--line-net-2); }
/* 스위처 메뉴(fixed, body 부착) */
.v2-ws-menu { z-index: 60; background: var(--bg); border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--shadow-2, 0 8px 30px rgba(var(--shadow-ink), .14)); padding: 6px; max-width: 380px; max-height: 74vh; overflow: auto; display: flex; flex-direction: column; gap: 2px; }
.v2-ws-acct { font-size: 11.5px; color: var(--muted); padding: 6px 8px 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-ws-sec { font-family: var(--mono, ui-monospace, monospace); font-size: 10px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted-2); padding: 8px 8px 3px; }
.v2-ws-cur { display: flex; align-items: center; gap: 7px; padding: 7px 8px; border-radius: 8px; background: var(--bg-tint); }
.v2-ws-cur .v2-ws-name { font-size: 13px; }
.v2-ws-check { color: var(--blue); font-weight: 800; flex: none; }
.v2-ws-item { display: flex; align-items: center; gap: 6px; padding: 8px; border: 0; background: none; font: inherit; font-size: 12.5px; font-weight: 600; color: var(--ink-sub); text-decoration: none; border-radius: 8px; cursor: pointer; text-align: left; }
.v2-ws-item:hover { background: var(--bg-tint); color: var(--ink); }
.v2-ws-item.add { color: var(--blue); }
.v2-ws-empty, .v2-ws-loading { font-size: 11.5px; color: var(--muted); line-height: 1.55; padding: 4px 8px 6px; margin: 0; }
.v2-ws-team-row { display: flex; align-items: center; gap: 4px; padding: 2px 4px 2px 8px; border-radius: 8px; }
.v2-ws-team-row:hover { background: var(--bg-tint); }
/* 행 본체 — a(연결한 팀)와 button(registry 전환) 둘 다 이 클래스를 쓴다. button 기본 테두리·배경을
   리셋하지 않으면 이름까지만 감싼 회색 상자가 되고 ✎·✕ 가 상자 밖에 남는다(2026-08-19 실측). */
.v2-ws-team-open { flex: 1; min-width: 0; display: flex; align-items: center; gap: 6px; text-decoration: none; color: var(--ink); font: inherit; font-size: 12.5px; font-weight: 600; border: 0; background: none; padding: 5px 2px; text-align: left; cursor: pointer; border-radius: 6px; }
.v2-ws-err { flex: none; width: 15px; height: 15px; border-radius: 50%; background: var(--coral); color: var(--on-fill); font-size: 10px; font-weight: 800; display: grid; place-items: center; }
.v2-ws-auto { flex: none; font-size: 10.5px; font-weight: 700; padding: 2px 6px; border: 1px solid var(--line); border-radius: 6px; background: none; color: var(--muted); cursor: pointer; }
.v2-ws-auto.on { color: var(--mint-deep); border-color: var(--ok-line-2); background: var(--bg-success); }
.v2-ws-del { flex: none; width: 22px; border: 0; background: none; color: var(--muted-2); font-size: 12px; cursor: pointer; border-radius: 6px; }
.v2-ws-del:hover { color: var(--coral); background: var(--bg-tint); }
.v2-ws-linkform { display: flex; flex-direction: column; gap: 6px; padding: 6px 8px 8px; }
.v2-ws-in { width: 100%; box-sizing: border-box; padding: 7px 9px; border: 1px solid var(--line); border-radius: 8px; font: inherit; font-size: 12.5px; }
.v2-ws-in:focus { outline: none; border-color: var(--blue); }
.v2-ws-formrow { display: flex; align-items: center; gap: 8px; }
.v2-ws-note { font-size: 11px; color: var(--coral); flex: 1; min-width: 0; line-height: 1.4; }
.v2-ws-hint { font-size: 11px; color: var(--muted); line-height: 1.5; margin: 2px 0 0; }
.v2-ws-promo { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: 8px; }
.v2-ws-promo:hover { background: var(--bg-tint); }
.v2-ws-promo-main { flex: 1; min-width: 0; display: flex; align-items: center; gap: 6px; }
.v2-ws-promo-kind { flex: none; font-family: var(--mono, ui-monospace, monospace); font-size: 9.5px; color: var(--muted); border: 1px solid var(--line); border-radius: 4px; padding: 0 4px; }
.v2-ws-promo-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; font-weight: 600; color: var(--ink); }
.v2-ws-promo-acts { flex: none; display: flex; gap: 4px; }

/* ── 사이드바 ── */
/* ★사이드바 좌표계(상민님 2026-08-19 "여백·폰트·스크롤바 밸런스가 하나도 안 맞는다") — 규칙 셋만 지킨다.
   ① **글자 기둥 하나**: 모든 행의 글자가 --rail 에서 시작한다. 실측(재설계 전)은 헤더 18 · 리브 54 ·
      프로젝트 62.5(펼치면 65.5) · 세션 41 · 내 이름 48 로 다섯 갈래였고, 특히 자식(세션 41)이 부모(62.5)보다
      **왼쪽**에서 시작해 위계가 뒤집혀 읽혔다. 세션의 상태점은 프로젝트의 폴더 아이콘 칸에 앉혀 기둥을 맞춘다.
   ② **4px 격자**: 한 줄 행은 모두 --row-h(34px). 이전엔 38.5 / 36.5 / 30.2 로 행마다 달랐다.
   ③ **글자 크기 넷**: 14(이름) · 13(세션·버튼) · 12(부제) · 11(시각·개수·라벨). 이전엔 9.5~15 사이 열한 가지였다.
   ⚠ 단, 기둥 규칙은 **최상위 행(홈·리브·프로젝트)에만** 적용한다. 세션까지 같은 기둥에 세웠더니 부모와 자식이
      같은 x(실측 56·56)에 서서 '프로젝트 안에 세션이 있다'가 화면에서 사라졌다 — 원준님 2026-08-20 반려
      ("프로젝트 아래 방처럼 있는 게 다 없어졌다"). 자식은 --nest 만큼 안쪽에 선다(56 → 70).
      ①의 원래 사유(자식 41 < 부모 62.5 로 위계가 **뒤집혀** 읽힘)는 그대로 지켜진다 — 이제 자식이 더 안쪽이다. */
.v2-side { --side-x: 8px; --rail: 56px; --nest: 14px; --row-h: 34px; background: var(--canvas); border-right: 1px solid var(--line); display: flex; flex-direction: column; min-height: 0; }
/* 좌상단 한 줄 = **워크스페이스 머리글**. 워드마크 줄을 따로 두면 조직명이 'Lively' 일 때 같은 글자가
   두 번 나오고 머리만 196px 를 먹었다(실측) → 한 줄로. 브랜드 네모(홈 링크)는 무엇인지 읽히지 않아
   걷었고(상민님 2026-08-19), 홈은 아래 [홈] 줄이 맡는다. */
.v2-side-top { padding: 10px var(--side-x, 8px) 4px; display: flex; align-items: center; }
/* 워크스페이스 문패 카드(#1719 개편) — 한 줄 스위처를 카드로 격상. '여기가 어느 집인가'는 목록을 읽기 전에
   얼굴이 말한다: 팀 = 조직 이니셜 타일 + 멤버 얼굴 스택, 개인 = 내 얼굴(원형). */
.v2-ws.v2-wscard { padding: 9px 10px; border: 1px solid var(--line-net); border-radius: 11px; background: var(--bg); gap: 10px; }
.v2-ws.v2-wscard:hover { border-color: var(--blue); }
.v2-wscard-big { width: 34px; height: 34px; border-radius: 9px; background: var(--ink); color: var(--on-fill); display: inline-grid; place-items: center; font-size: 16px; font-weight: 800; flex: none; overflow: hidden; }
.v2-wscard-big.round { border-radius: 50%; font-size: 13px; }
.v2-wscard-big.round img { width: 100%; height: 100%; object-fit: cover; }
.v2-wscard-tt { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.3; }
.v2-wscard-tt b { font-size: 14px; font-weight: 700; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-wscard-tt span { font-size: 11px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-wscard-faces { display: flex; flex: none; align-items: center; }
.v2-wscard-face { width: 18px; height: 18px; border-radius: 50%; border: 2px solid var(--bg); margin-left: -6px; font-size: 8px; font-weight: 800; color: var(--on-fill); display: inline-grid; place-items: center; overflow: hidden; flex: none; }
.v2-wscard-face:first-child { margin-left: 0; }
.v2-wscard-face img { width: 100%; height: 100%; object-fit: cover; }
.v2-wscard-more { width: 18px; height: 18px; border-radius: 50%; border: 2px solid var(--bg); margin-left: -6px; background: var(--bg-tint-2); color: var(--muted); font-style: normal; font-size: 8px; font-weight: 800; display: inline-grid; place-items: center; flex: none; }
/* 개인 워크스페이스 = 웜 톤 캔버스 — 곁눈으로도 '지금 어느 집인가'가 잡힌다(슬랙 워크스페이스별 색의 절제판).
   액센트·글자는 그대로, 바탕의 온도만 바꾼다. */
.v2-side.ws-personal, .ws-personal .stu-panel { background: var(--bg-tint); }
.ws-personal .v2-ws.v2-wscard, .ws-personal .v2-fixed { border-color: #E8E2D4; }
/* 늘 있는 곳(홈·리브) — 프로젝트 행과 **같은 모양**이다. 알약(테두리·큰 글씨)으로 만들면 목록보다 먼저
   읽혀 위계가 뒤집힌다(상민님 2026-08-19). 아이콘도 프로젝트 폴더와 같은 칸에 앉아 글자가 기둥 56px 에 선다. */
/* 바로 가기 칸 — 아래 경계를 끌어 높이를 줄일 수 있다(#1719 원준 2026-08-24: "세션 보여줄 길이를 더 길게").
   --v2-navh 는 그 손잡이(navSplitter)가 이 요소에 직접 써 넣는다. 값이 없으면 종전처럼 내용만큼. */
.v2-fixed { padding: 0 var(--side-x, 8px) 6px; margin-bottom: 0; border-bottom: 1px solid var(--line); display: flex; flex-direction: column; gap: 2px;
  max-height: var(--v2-navh, none); overflow: hidden; }
/* 그 경계선 자체가 손잡이다 — 평소엔 티 나지 않다가 손을 올리면 파랗게 굵어진다(잡을 수 있다는 표시). */
.v2-navsplit { height: 7px; margin-bottom: 1px; }
.v2-navsplit::after {
  content: ""; position: absolute; left: 14px; right: 14px; top: 3px; height: 1px; border-radius: 1px;
  background: transparent; transition: background-color 120ms ease, transform 120ms ease; }
.v2-navsplit:hover::after, .v2-navsplit:focus-visible::after, .v2-navsplit.on::after {
  background: var(--blue); transform: scaleY(2); }
/* ⚠ 고정 행(새 작업·확인할 것·외부 앱 연결·리브)은 **프로젝트 행과 같은 무게**여야 한다(원준 2026-08-20:
   "존재가 너무 없고 안 중요한 버튼 같다"). 자리는 이미 같았다 — 아이콘 36 · 글자 56 · 높이 34 로 프로젝트와
   동일. 다른 건 **크기·굵기·색 셋뿐**이었고(13/600/ink-sub vs 14/700/ink) 그 셋이 "덜 중요한 것"으로 읽히게
   만들었다. 이 줄들은 목록의 항목이 아니라 **목록과 같은 급의 갈 곳**이므로 같은 잉크·같은 굵기로 세운다. */
.v2-nav { display: flex; align-items: center; padding: 7px 10px 7px 28px; min-height: var(--row-h, 34px); border-radius: 8px; font-size: 14px; font-weight: 700; line-height: 1.4; color: var(--ink); text-decoration: none; }
.v2-nav:hover { background: var(--bg); color: var(--ink); }
.v2-nav.on { background: var(--bg); color: var(--ink); font-weight: 700; box-shadow: inset 0 0 0 1px var(--line-net); }
.v2-nav .n { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-nav .v2-nav-cnt { margin-left: auto; min-width: 17px; height: 17px; padding: 0 5px; border-radius: 9px; background: var(--warn-deep); color: var(--on-fill); font-size: 10.5px; font-weight: 800; display: inline-grid; place-items: center; flex: none; font-variant-numeric: tabular-nums; }
.v2-nav-ic { width: 16px; height: 16px; margin-right: 4px; flex: none; fill: none; stroke: var(--muted-2); stroke-width: 1.8; stroke-linejoin: round; }
.v2-nav:hover .v2-nav-ic, .v2-nav.on .v2-nav-ic { stroke: var(--blue); }
.v2-nav-lm { width: 16px; height: 16px; margin-right: 4px; flex: none; border-radius: 50%; background: var(--bg-success); border: 1px solid var(--ok-line-2); display: grid; place-items: center; color: var(--mint-deep); font-weight: 800; font-size: 9px; }
.v2-side-sec { padding: 14px 8px 4px 16px; display: flex; align-items: center; gap: 2px; flex-wrap: nowrap; min-height: 30px; }
.v2-side-sec .v2-k { margin-right: 6px; font-family: inherit; font-size: 11px; font-weight: 700; letter-spacing: 0; text-transform: none; color: var(--muted); font-variant-numeric: tabular-nums; }
/* 개수가 늘어도(196·1204) 줄바꿈되지 않게 — 조작부가 두 줄로 접히면 목록보다 머리가 커 보인다. */
.v2-side-sec .v2-k { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.v2-side-sec .v2-flt-btn, .v2-side-sec .v2-add { flex: none; white-space: nowrap; }
/* ＋도 아이콘 — 돋보기가 자리를 차지하면서 글자 버튼까지 두면 헤더가 두 줄로 접힌다(#1067 의 🔍/＋ 문법). */
.v2-add { flex: none; display: inline-grid; place-items: center; width: 27px; height: 27px; color: var(--muted); text-decoration: none; border: 1px solid transparent; border-radius: 7px; }
.v2-add:hover { color: var(--ink); background: var(--bg); border-color: var(--line); }
.v2-add.on { color: var(--blue); background: var(--bg); border-color: var(--line); }
.v2-add-ic { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
/* ＋ 새 프로젝트 팝오버 — anchoredPopover 는 자리만 잡는다. 면(배경·테두리·그림자)은 이 클래스가 줘야 하고,
   없으면 입력칸·안내글이 본문 위에 투명하게 겹친다(상민님 2026-08-19 실측 사진). */
/* 상태 칩 — 살아 있는 세션 상태별 개수. 누르면 그 상태만(렌즈). 채운 파랑은 안 쓴다(주 액션 아님) — 켜짐은 흰 배경+테두리. */
/* 돋보기 — 검색칸을 여닫는다. 아이콘 자체는 늘 보여서 '검색이 있는 줄 모르는' 일이 없다(#1154 반려 사유 대응).
   검색어가 남아 있으면 켜진 색으로 남아, 목록이 짧아진 이유를 헤더가 말해 준다. */
.v2-findbtn-wrap { flex: none; display: inline-flex; }
.v2-findbtn { display: inline-grid; place-items: center; width: 27px; height: 27px; padding: 0; border: 1px solid transparent; border-radius: 7px; background: none; color: var(--muted); cursor: pointer; }
.v2-findbtn:hover, .v2-findbtn.on { color: var(--ink); background: var(--bg); border-color: var(--line); }
.v2-findbtn.has { color: var(--blue-deep); }
.v2-findbtn-ic { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }

/* [필터] — 조작부는 버튼 하나. 팝오버 안에 상태·범위·완료가 모인다(#1719 사이드바 재구성). */
.v2-flt { position: relative; flex: none; }
.v2-flt-btn { display: inline-flex; align-items: center; gap: 5px; height: 27px; padding: 0 9px; border: 1px solid transparent; border-radius: 7px; background: none; font: inherit; font-size: 12px; font-weight: 700; color: var(--muted); cursor: pointer; }
.v2-flt-btn:hover, .v2-flt-btn.open { color: var(--ink); background: var(--bg); border-color: var(--line); }
.v2-flt-btn.has { color: var(--blue-deep); }
.v2-flt-ic { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
.v2-flt-n { min-width: 15px; height: 15px; border-radius: 999px; background: var(--blue-fill); color: var(--on-fill); font-size: 10px; font-weight: 800; display: inline-grid; place-items: center; padding: 0 3px; }
.v2-flt-pop { position: absolute; top: calc(100% + 6px); right: -40px; width: 236px; z-index: 30; background: var(--bg); border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 12px 32px rgba(var(--shadow-ink), .14); padding: 6px; }
.v2-flt-k { font-family: var(--mono, ui-monospace, monospace); font-size: 11px; letter-spacing: .06em; color: var(--muted); padding: 8px 10px 3px; }
.v2-fo { display: flex; align-items: center; gap: 9px; width: 100%; padding: 8px 10px; border: 0; border-radius: 8px; background: none; font: inherit; font-size: 13.5px; font-weight: 600; color: var(--ink-sub); cursor: pointer; text-align: left; }
.v2-fo:hover { background: var(--bg-tint); color: var(--ink); }
.v2-fo.on { color: var(--ink); background: var(--bg-tint); }
.v2-fo .n { flex: 1; min-width: 0; }
.v2-fo-pad { width: 7px; flex: none; }
.v2-fo-ck { color: var(--mint-deep); font-weight: 800; }
.v2-flt-foot { display: flex; justify-content: space-between; border-top: 1px solid var(--line); margin-top: 6px; padding: 6px 4px 2px; }
/* 필터가 켜졌을 때만 나오는 요약 한 줄 — 목록이 왜 짧은지 화면이 직접 말한다. */
.v2-flt-sum { display: flex; align-items: center; gap: 8px; margin: 4px var(--side-x, 8px) 0; padding: 5px 10px; border: 1px dashed var(--line-net); border-radius: 8px; font-size: 11.5px; font-weight: 600; color: var(--ink-sub); background: var(--bg); }
.v2-flt-sum span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 스크롤 막대 — 기본 막대는 이 연한 캔버스 위에서 굵고 어둡게 튄다. 얇은 알약으로 바꾸고 **자리를 늘 차지하게**
   둔다(나타났다 사라지면 그때마다 목록 전체가 좌우로 흔들린다). 투명 테두리로 안쪽 여백을 만든다. */
.v2-tree { flex: 1; min-height: 0; overflow-y: scroll; overflow-x: hidden; padding: 2px 10px 14px var(--side-x, 8px); scrollbar-width: thin; scrollbar-color: var(--muted-3) transparent; }
.v2-tree::-webkit-scrollbar { width: 10px; }
.v2-tree::-webkit-scrollbar-track { background: transparent; }
.v2-tree::-webkit-scrollbar-thumb { background: var(--muted-3); border-radius: 8px; border: 3px solid transparent; background-clip: padding-box; }
.v2-tree:hover::-webkit-scrollbar-thumb { background: var(--muted-2); background-clip: padding-box; }
.v2-pj + .v2-pj { margin-top: 2px; }
/* 카드(펼친 프로젝트)는 앞뒤로 더 띄운다 — 상자끼리 붙으면 한 덩어리로 뭉개진다. */
.v2-pj.open + .v2-pj, .v2-pj + .v2-pj.open { margin-top: 8px; }
/* ★펼친 프로젝트 = 흰 카드 그릇 (안 1 '방', 상민님 선택 2026-08-18) — 세션이 프로젝트의 **안**에
   산다는 걸 면(面)이 말한다. 들여쓰기+세로선만으로는 "목록 둘이 이웃한 그림"으로 읽혔다(반려 사유).
   접힌 프로젝트는 카드 없이 조용히 — 카드는 '열려 있음'의 표식이기도 하다. */
.v2-pj.open { background: var(--bg); border: 1px solid var(--line-net); border-radius: 10px; }
.v2-pj.open > .v2-pj-row { padding: 7px 9px 7px 7px; border-radius: 9px 9px 0 0; }
.v2-pj.open > .v2-pj-row:hover { background: var(--bg-tint); }
.v2-pj.open > .v2-pj-row.on { background: var(--bg-tint); box-shadow: none; }
/* 프로젝트 행 — 폴더 + 굵은 이름. 누르면 **프로젝트 화면**. 완료·조용함도 이름은 같은 잉크색(태그·시각이 구분). */
.v2-pj-row { display: flex; align-items: center; gap: 4px; padding: 7px 10px 7px 8px; min-height: var(--row-h, 34px); border-radius: 8px; font-size: 14px; font-weight: 700; line-height: 1.4; color: var(--ink); text-decoration: none; }
.v2-pj-row:hover { background: var(--bg); }
/* ＋ 새 프로젝트 한 줄 — 트리 바로 위에 돋는다. 프로젝트 줄과 같은 들여쓰기·같은 폴더 아이콘이라
   '지금 이 목록에 하나 생긴다'가 눈으로 읽힌다(팝오버를 걷은 이유가 이것이다, 원준 2026-08-21). */
.v2-npj { padding: 2px 10px 2px var(--side-x, 8px); }
.v2-npj-l { display: flex; align-items: center; gap: 4px; padding: 6px 9px 6px 7px; min-height: var(--row-h, 34px);
  border: 1px solid var(--blue); border-radius: 8px; background: var(--bg); box-shadow: 0 0 0 3px rgba(45,107,240,.10); }
.v2-npj-l .v2-pj-ic { stroke: var(--blue); }
.v2-npj-l.sending { opacity: .6; }
.v2-npj-in { flex: 1; min-width: 0; padding: 0; border: 0; background: none; font: inherit; font-size: 14px; font-weight: 700; line-height: 1.4; color: var(--ink); }
.v2-npj-in:focus { outline: none; }
.v2-npj-in::placeholder { font-weight: 400; color: var(--muted-2); }
.v2-npj-err { margin: 4px 0 0 30px; font-size: 11.5px; line-height: 1.45; color: var(--coral-text); }
.v2-pj-row.on { background: var(--bg); box-shadow: inset 0 0 0 1px var(--line-net); }
.v2-pj-ic { width: 16px; height: 16px; flex: none; fill: none; stroke: var(--muted-2); stroke-width: 1.8; stroke-linejoin: round; }
.v2-pj-row:hover .v2-pj-ic, .v2-pj-row.on .v2-pj-ic { stroke: var(--blue); }
.v2-pj-row .n { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-pj-when { font-size: 11px; font-variant-numeric: tabular-nums; color: var(--muted); flex: none; margin-left: 8px; min-width: 34px; text-align: right; }
.v2-tag { font-size: 11px; letter-spacing: 0; color: var(--muted); border: 1px solid var(--line-net); border-radius: 4px; padding: 0 5px; line-height: 16px; flex: none; margin-left: 6px; }
/* 프로젝트 행 오른쪽 상태 요약 — 색 점 + 개수. 확인 필요 › 작업 완료 › 작업 중 › 그 밖(회색) 순. */
.v2-sums { display: inline-flex; align-items: center; justify-content: flex-end; gap: 8px; flex: none; margin-left: 8px; min-width: 34px; }
.v2-sum { display: inline-flex; align-items: center; gap: 4px; font-family: var(--mono, ui-monospace, monospace); font-size: 11px; font-weight: 600; color: var(--muted); }
.v2-sum.wait { color: var(--warn-deep); }
.v2-sum.busy { color: var(--blue); }
.v2-sum.done { color: var(--mint-deep); }
/* ⚠ 정사각(16×16)이어야 한다 — 펼침 상태에서 90° 회전하면 **박스의 세로가 가로로 온다**. 16×20 이던 때는
   회전 뒤 시각 폭이 20px 이 되어 좌우로 2px 씩 삐져나왔고, 오른쪽 2px 이 폴더 아이콘을 파고들어 아이콘이
   가려 보였다(원준 2026-08-20 신고 · 실측: 접힘 캐럿 16–32/틈 4px vs 펼침 14–34/틈 2px).
   정사각이면 회전해도 시각 범위가 그대로라 기둥(캐럿 16 → 폴더 36 → 글자 56)이 흔들리지 않는다. */
.v2-car { width: 16px; height: 16px; border: 0; background: none; color: var(--muted-2); font-size: 14px; line-height: 1; border-radius: 4px; cursor: pointer; padding: 0; transition: transform .15s ease; flex: none; }
.v2-car:hover { color: var(--ink); background: var(--bg-tint-2); }
.v2-car.none { visibility: hidden; cursor: default; }
.v2-pj.open > .v2-pj-row .v2-car { transform: rotate(90deg); }
/* 세션 목록 = 카드 몸통 — 담김은 카드(면)가 말하므로 세로선 레일은 뺀다(이중 표식은 잡음).
   세션 행: 상태점 + 보통 글씨. 누르면 **그 세션의 대화**. 프로젝트 행과 생김새가 다르다(위계). */
.v2-ss-list { padding: 0 9px 6px 0; }
.v2-ss-row { position: relative; display: flex; align-items: center; gap: 0; padding: 7px 9px 7px calc(27px + var(--nest, 14px)); border-radius: 7px; font-size: 13px; font-weight: 500; line-height: 1.4; color: var(--ink-sub); text-decoration: none; min-height: var(--row-h, 34px); }
.v2-ss-row + .v2-ss-row { margin-top: 2px; }
/* 점은 프로젝트의 폴더 아이콘과 같은 칸(16px)의 한가운데 — 이 여백이 세션 글자를 부모와 같은 기둥에 세운다. */
.v2-ss-row > .v2-dot { margin: 0 9px 0 5px; }
.v2-ss-row:hover { background: var(--bg-tint); color: var(--ink); }
.v2-ss-row.on { background: var(--bg-tint); color: var(--ink); font-weight: 700; }
/* 지금 보고 있는 세션 — 행 왼쪽에 파란 마디. */
.v2-ss-row.on::before { content: ''; position: absolute; left: calc(3px + var(--nest, 14px)); top: 7px; bottom: 7px; width: 2.5px; border-radius: 2px; background: var(--blue-fill); }
.v2-ss-go { width: 14px; height: 14px; margin-left: 6px; flex: none; fill: none; stroke: var(--muted-2); stroke-width: 1.8; stroke-linejoin: round; opacity: 0; }
/* 보관(×) — 자리는 늘 차지하고 hover 때만 보인다(압정과 같은 규약: 나타나며 행을 밀면 목록이 흔들린다). */
.v2-ss-x { width: 18px; height: 18px; margin-left: 6px; padding: 0; flex: none; border: 0; border-radius: 5px; background: none; color: var(--muted-2); cursor: pointer; display: inline-grid; place-items: center; opacity: .45; }
.v2-ss-row:hover .v2-ss-x, .v2-ss-x:focus-visible { opacity: 1; }
/* 모바일·터치엔 hover 가 없다 — 늘 또렷하게. */
@media (hover: none) { .v2-ss-x { opacity: 1; } }
.v2-ss-x:hover { color: var(--danger); background: var(--bg-tint-2); }
.v2-ss-x-ic { width: 12px; height: 12px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }
/* 이름 인라인 편집 — 행의 글자 자리를 그대로 쓴다(칸이 튀어나오면 목록이 흔들린다). */
.v2-ss-edit { width: 100%; min-width: 0; margin: -2px 0; padding: 1px 5px; border: 1px solid var(--blue); border-radius: 5px; background: var(--bg); font: inherit; font-size: 13px; font-weight: 500; color: var(--ink); }
.v2-ss-edit:focus { outline: none; box-shadow: 0 0 0 2px color-mix(in srgb, var(--blue) 22%, transparent); }
/* 보관 안내의 '다시 안내하지 않기' */
.v2-arch-ack { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--ink-sub); cursor: pointer; }
.v2-arch-ack input { width: 15px; height: 15px; accent-color: var(--blue); cursor: pointer; }
.v2-ss-row:hover .v2-ss-go { opacity: 1; }
.v2-ss-main { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.35; }
.v2-ss-row .t { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-ss-row .sub { font-size: 12px; font-weight: 500; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: 1px; }
.v2-ss-face { width: 18px; height: 18px; margin-left: 6px; border-radius: 50%; font-size: 10px; font-weight: 700; flex: none; display: inline-grid; place-items: center; color: var(--on-fill); overflow: hidden; }
.v2-ss-face img { width: 100%; height: 100%; object-fit: cover; }
.v2-ss-row .w { font-size: 11px; font-variant-numeric: tabular-nums; color: var(--muted); flex: none; font-weight: 600; margin-left: 6px; }
.v2-ss-row .w.wait { color: var(--warn-deep); }
.v2-ss-row .w.busy { color: var(--blue); }
.v2-ss-row .w.done { color: var(--mint-deep); }
.v2-ss-more { display: block; padding: 6px 9px 6px 47px; font-size: 12px; color: var(--muted); text-decoration: none; }
/* '지난 세션 n' — 멈춘 세션을 접어 두는 묶음 머리(#1808). 캐럿·글자 시작점을 **세션 행과 같은 안쪽 기둥**에
   맞춘다(--nest 포함) — 위계를 한 단 더 들이는 게 아니라 그 방 안의 묶음이라는 뜻이다. */
.v2-ss-past { display: flex; align-items: center; gap: 4px; width: calc(100% - 9px); margin-top: 2px; padding: 5px 9px 5px calc(27px + var(--nest, 14px)); border: 0; background: none; font: inherit; font-size: 12px; font-weight: 600; line-height: 1.4; color: var(--muted); cursor: pointer; border-radius: 7px; text-align: left; }
.v2-ss-past:hover { background: var(--bg-tint); color: var(--ink); }
.v2-ss-past .n { flex: none; }
.v2-ss-past .v2-cnt { flex: none; }
.v2-ss-past .v2-car { transition: transform .15s ease; }
.v2-ss-past.open .v2-car { transform: rotate(90deg); }
/* 지난 세션 행 — 이름은 같은 잉크색이다(흐린 회색 본문 금지). 굵기만 한 급 낮춰 '지금 도는 것'과 결을 가른다. */
.v2-ss-row.past .t { font-weight: 450; }
.v2-tree-note { margin: 10px var(--side-x, 8px) 0 0; padding: 10px 12px; border: 1px dashed var(--line-net); border-radius: 9px; font-size: 13px; color: var(--muted); line-height: 1.55; display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }
.v2-tree-note .btn-text { font-size: 13px; padding: 0; }
/* 「전체 프로젝트 · N」 — 진행 중이 아닌 것들을 접어 두는 묶음 머리(#1719 개편 안2). 섹션 라벨의 결로,
   글자 기둥은 프로젝트 행과 같다. */
.v2-all-h { display: flex; align-items: center; gap: 4px; width: 100%; margin-top: 14px; padding: 7px 10px 7px 8px; border: 0; background: none; font: inherit; font-size: 12px; font-weight: 700; color: var(--muted); cursor: pointer; border-radius: 8px; text-align: left; }
.v2-all-h:hover { background: var(--bg); color: var(--ink); }
.v2-all-h .n { flex: none; }
.v2-all-h .v2-car { transition: transform .15s ease; }
.v2-all-h.open .v2-car { transform: rotate(90deg); }
.v2-tree-more { display: block; width: calc(100% - var(--side-x, 8px)); margin-top: 10px; padding: 8px 10px; border: 1px dashed var(--line-net); border-radius: 8px; background: none; font: inherit; font-size: 12px; font-weight: 600; color: var(--muted); cursor: pointer; text-align: left; }
.v2-tree-more:hover { color: var(--ink); background: var(--bg); }
/* 고정 단추 — 자리는 늘 차지한다(hover 때 나타나며 행을 밀면 목록이 흔들린다). 고정된 것만 늘 보인다. */
/* ＋ 새 세션(프로젝트 줄) — 핀과 같은 규칙: 자리는 늘 차지하고 손을 얹었을 때만 보인다(원준 2026-08-20). */
.v2-newb { width: 18px; height: 18px; margin-left: 2px; padding: 0; flex: none; border: 0; border-radius: 5px; background: none; color: var(--muted-2); cursor: pointer; display: inline-grid; place-items: center; opacity: 0; }
.v2-pj-row:hover .v2-newb, .v2-newb:focus-visible { opacity: 1; }
.v2-newb:hover { color: var(--blue); background: var(--bg-tint-2); }
.v2-newb-ic { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }

.v2-pinb { width: 18px; height: 18px; margin-left: 4px; padding: 0; flex: none; border: 0; border-radius: 5px; background: none; color: var(--muted-2); cursor: pointer; display: inline-grid; place-items: center; opacity: 0; }
.v2-pj-row:hover .v2-pinb, .v2-pinb:focus-visible { opacity: 1; }
.v2-pinb:hover { color: var(--ink); background: var(--bg-tint-2); }
.v2-pinb.on { opacity: 1; color: var(--blue); }
.v2-pinb-ic { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linejoin: round; stroke-linecap: round; }
/* 고정됨 = 속이 찬 핀. ⚠ stroke 를 끄지 않는다 — 바늘(M12 17v5)은 선이라 fill 로는 안 그려져서,
   stroke:none 이면 바늘이 통째로 사라진 '머리만 남은 핀'이 된다. */
.v2-pinb.on .v2-pinb-ic { fill: currentColor; }
/* 고정 묶음과 나머지 사이 — 실선 하나면 충분하다(머리글을 두지 않는다). */
.v2-pj.after-pins { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line-net); }

.v2-side-foot { padding: 8px var(--side-x, 8px) 10px; border-top: 1px solid var(--line); display: flex; flex-direction: column; gap: 4px; }
.v2-foot-k { padding: 2px 10px 0; font-size: 10.5px; font-weight: 800; letter-spacing: .06em; color: var(--muted); }
.v2-apps-btn { display: flex; align-items: center; gap: 4px; width: 100%; padding: 7px 10px 7px 28px; min-height: var(--row-h, 34px); border-radius: 8px; border: 0; background: none; font: inherit; font-size: 13px; font-weight: 600; color: var(--ink-sub); cursor: pointer; text-align: left; }
.v2-apps-btn:hover { background: var(--bg); color: var(--ink); }
.v2-apps-btn .v2-cnt { margin-left: auto; }
/* [나] — 행 전체가 [내 프로필 · 환경설정]을 여는 단추다(#1843). 생김새는 위 [앱] 줄과 같은 규격(같은 층이라
   같은 모양이어야 한다) — 손을 얹으면 배경이 들어오고, 오른쪽 톱니는 '설정이 여기 있다'는 표식이다. */
.v2-me { display: flex; align-items: center; gap: 8px; width: 100%; padding: 4px 10px 4px 18px; min-height: var(--row-h, 34px); border: 0; border-radius: 8px; background: none; font: inherit; font-size: 13px; color: var(--ink-sub); cursor: pointer; text-align: left; }
.v2-me:hover { background: var(--bg); color: var(--ink); }
.v2-me .v2-ava { width: 22px; height: 22px; border-radius: 50%; font-size: 10px; flex: none; }
.v2-me-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-me-ic { width: 15px; height: 15px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linejoin: round; color: var(--muted-2); }
.v2-me:hover .v2-me-ic { color: var(--ink-sub); }

/* ── 중앙 ── */
.v2-main { position: relative; min-width: 0; min-height: 0; overflow: hidden; display: flex; flex-direction: column; background: var(--bg); }   /* relative: 타임라인 서랍 버튼(.v2-tl-btn)의 기준 */

/* ── 셸 탭(#1719) — 가운데 열 맨 위 한 줄. 탭 = 화면(홈·프로젝트·세션·앱) 하나, 전환은 숨겼다 보였다(재렌더 없음). ── */
/* ══ 최상단 탭 = 폐지한 세션 탭 줄의 문법(원준 2026-08-20) ══════════════════════════════
   종전엔 회색 바탕 위의 **둥근 알약**이라 탭이 아니라 배지로 읽혔다("탭 같지가 않아서 별로"). 브라우저·에디터의
   탭 문법으로 바꾼다 — 줄은 한 톤 낮은 띠(#FAFBFC), 켜진 탭만 **흰 종이로 올라오고 위쪽에 파란 밑줄**이 그어진다.
   테두리·그림자를 걷어 낸 자리를 '면의 높낮이'가 대신하므로 탭이 몇 개든 줄이 조용하다.
   아이콘(집·말풍선·폴더)은 그대로 두되 **아이콘 색이 곧 상태**다(.st-busy/wait/done). */
.v2-tabs { display: flex; align-items: stretch; gap: 0; height: 37px; padding: 0; border-bottom: 1px solid var(--line); background: var(--gray-bg-2); flex: none; overflow: hidden; }
/* 굴러가는 건 안쪽 줄뿐 — [모든 탭] 끝막이는 그 바깥에 있어 지나가는 탭을 덮지 않는다. */
.v2-tabs-scroll { flex: 1; min-width: 0; display: flex; align-items: stretch; gap: 1px; overflow-x: auto; scrollbar-width: none; }
.v2-tabs-scroll::-webkit-scrollbar { display: none; }
.v2-tabs::-webkit-scrollbar { display: none; }
/* 폭은 **줄을 n 등분**한다(상민님 2026-08-20 "탭 길이 전체 탭 섹션의 1/n 으로 균등하게").
   종전엔 활성 탭만 190px, 나머지는 118~220px 사이에서 내용대로 늘었다 — 같은 줄의 탭인데 크기가 제각각이라
   '지금 켜진 것'과 '이름이 긴 것'이 같은 신호(넓다)로 보였다. 켜짐은 이제 **면과 밑줄**만으로 말한다.
   flex:1 1 0 이 곧 1/n 이고, 바닥 폭(min-width) 아래로 밀리면 그때부터 줄이 굴러간다 —
   글자가 아예 안 읽히는 탭 20개보다, 읽히는 탭 몇 개 + 스크롤 + [모든 탭] 목록이 낫다. */
/* ⚠ max-width 상한(상민님 2026-08-24) — 종전 none 이면 `flex: 1 1 0` 이 남는 폭을 전부 먹어, **탭이 하나일 때
   그 하나가 줄 전체로 늘어났다**(이름이 두 글자여도 화면 끝까지). 브라우저 탭 줄도 같은 이유로 상한을 둔다.
   상한을 넘긴 남는 폭은 빈 채로 남고, 데스크톱에선 그 자리가 곧 창을 끌 자리가 된다. */
.v2-tab { display: inline-flex; align-items: center; gap: 7px; height: 36px; padding: 0 9px 0 13px; border: 0; border-radius: 0; background: none; font-size: 12.5px; color: var(--muted-head); cursor: pointer; flex: 1 1 0; min-width: 96px; max-width: 240px; white-space: nowrap; user-select: none; }
.v2-tab:hover { background: rgba(255,255,255,.62); color: var(--ink); }
.v2-tab.on { background: var(--bg); box-shadow: inset 0 2px 0 var(--blue); color: var(--ink); font-weight: 700; }
.v2-tab.on:hover { background: var(--bg); }
/* 이름이 남은 폭을 다 먹는다 → ×는 **탭 오른쪽 끝**에 붙는다(원준 2026-08-20).
   종전엔 이름 바로 뒤에 붙어 있어 이름 길이마다 ×의 자리가 달랐다. */
.v2-tab .t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; text-align: left; }
.v2-tab-ic { width: 15px; height: 15px; stroke: currentColor; stroke-width: 1.8; fill: none; stroke-linecap: round; stroke-linejoin: round; flex: none; }
/* 상태는 아이콘 색으로 — 도는 중 파랑 · 확인 필요 앰버 · 끝남 민트. 글자색은 '켜짐/꺼짐'만 말한다(두 축을 섞지 않는다). */
.v2-tab-ic.st-busy { stroke: var(--blue); }
.v2-tab-ic.st-wait { stroke: var(--warn-deep); }
.v2-tab-ic.st-done { stroke: var(--mint-deep); }
.v2-tab .x { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 5px; color: var(--muted-2); flex: none; visibility: hidden; }
.v2-tab:hover .x, .v2-tab.on .x { visibility: visible; }
/* 연달아 닫는 동안(freeze)에는 **모든 탭의 ×를 띄워 둔다** — 오른쪽 탭이 커서 밑으로 미끄러져 들어와도
   그 탭에 hover 가 아직 안 걸려 ×가 안 보이면, 그 클릭이 '닫기'가 아니라 '탭 전환'이 된다(원준 2026-08-20). */
.v2-tabs.freeze .v2-tab .x { visibility: visible; }
.v2-tab .x:hover { background: var(--bg-punch); color: var(--ink); }
.v2-tab-xic { width: 10px; height: 10px; stroke: currentColor; stroke-width: 2.2; fill: none; stroke-linecap: round; }
.v2-tab-add { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 36px; border-radius: 0; color: var(--muted-head); flex: none; }
/* 탭의 × · ＋ 는 <button> — 브라우저 기본 버튼 테두리·회색 바탕을 벗긴다(안 벗기면 탭 안에 상자가 하나 더 그려진다, 모바일 크롬에서 두드러졌다 #1777). */
.v2-tab .x, .v2-tab-add { border: 0; background: none; padding: 0; font: inherit; cursor: pointer; appearance: none; -webkit-appearance: none; }
.v2-tab-add:hover { background: rgba(255,255,255,.62); color: var(--blue); }
/* 탭 패널 — 탭마다 한 벌(가운데·우패널). 숨긴 것은 자리도 차지하지 않는다. 스크롤은 패널 자기 것(탭마다 보존). */
.v2-tabpane { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; }
.v2-tabpane[hidden] { display: none; }
.v2-aside-pane { flex: 1; min-height: 0; overflow: hidden; display: flex; flex-direction: column; }
.v2-aside-pane[hidden] { display: none; }
/* 곁칸의 손님 화면(#1719, 2026-08-20) — 미리보기 iframe(v2/aside-slot.ts). 손님이 떠 있는 동안 원래 칸
   (발자취·파일)은 hidden 으로 물러날 뿐 사라지지 않는다 — 닫으면 쌓아 둔 발자취가 그대로 돌아온다. */
.v2-guest { flex: 1; min-height: 0; display: flex; flex-direction: column; background: var(--bg, #fff); }
/* 이름은 줄어드는 쪽 — [⟳ ↗ ×] 는 폭이 고정이라 잘리면 누를 것이 사라진다. */
.v2-guest-h .v2-guest-t { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 12px; color: var(--muted); }
.v2-guest-h .v2-guest-acts { flex: none; margin-left: auto; display: inline-flex; align-items: center; gap: 2px; }
/* 프레임은 남은 높이를 다 쓴다. 배경을 칠하는 이유는 로드 전 한 박자 동안 뒤가 비쳐 보이지 않게 하기 위해서다. */
.v2-guest-frame { flex: 1; min-height: 0; width: 100%; border: 0; background: var(--bg, #fff); }
.v2-center { width: 100%; max-width: 820px; margin: 0 auto; padding: 30px 40px 40px; }
.v2-eyebrow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 12.5px; color: var(--muted); }
.v2-title { margin: 8px 0 0; font-size: 24px; font-weight: 800; letter-spacing: -.5px; line-height: 1.3; }
.v2-desc { margin: 10px 0 0; font-size: 14.5px; color: var(--ink-sub); line-height: 1.7; max-width: 66ch; white-space: pre-line; }
.v2-actrow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 16px; }
.v2-sec { margin-top: 26px; }
.v2-sec-h { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.v2-list { border: 1px solid var(--line); border-radius: 12px; background: var(--bg); overflow: hidden; }
.v2-row { display: flex; align-items: center; gap: 12px; padding: 11px 14px; text-decoration: none; color: inherit; }
.v2-row + .v2-row { border-top: 1px solid var(--line-row); }
.v2-row:hover { background: var(--bg-tint); }
.v2-row-main { min-width: 0; flex: 1; }
.v2-row .t { font-size: 14px; font-weight: 700; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-row .m { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.v2-row-r { color: var(--muted-2); }
.v2-more { display: block; padding: 9px 14px; font-size: 12.5px; color: var(--muted); text-decoration: none; border-top: 1px solid var(--line-row); }

/* 홈 — 인사 + 입력창 하나(#1719, claude.ai 홈처럼) + 지금 도는 세션 */
.v2-home { flex: 1; min-height: 0; display: flex; flex-direction: column; width: 100%; max-width: 780px; margin: 0 auto; padding: 34px 32px 18px; }
/* 홈 = 런처(#1719 재설계) — 왼끝 정렬(가운데 정렬 낙수형 탈피), 입력 카드가 유일한 주인공. */
/* 카드 폭은 **아래 네 칸(실행 노드·제공자·모델·추론강도)이 한 줄에 들어가는 폭**으로 잡는다(원준 2026-08-20).
   실측(1440px, 2026-08-20): 제공자 'Anthropic · Claude Code' 가 글자만 134px + 셀렉트 좌우 여백 26px = 160px 이라
   종전 max-width 150px 에서 잘렸다. 네 칸(180+175+121+142) + 칸 사이 18 + [시키기] 84 + 사이 10 + 카드 안쪽 32 ≒ 762px. */
/* 홈 = 시키는 칸 하나(원준 2026-08-20 — 아래 세션 목록을 걷었다). 목록이 받쳐 주던 무게가 사라졌으므로
   칸을 **화면 한가운데**에 세운다. 위로만 붙여 두면 아래가 통째로 빈 화면이 된다. */
.v2-home-launch { max-width: 820px; justify-content: center; padding-top: 24px; padding-bottom: clamp(40px, 14vh, 130px); }
.v2-home-eyebrow { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.v2-home-eyebrow .sep { color: var(--line-net-2); }
.v2-home-eyebrow .st { display: inline-flex; align-items: center; gap: 5px; font-weight: 600; color: var(--ink-sub); }
.v2-home-eyebrow .st.wait { color: var(--warn-deep); }
.v2-home-launch .v2-h1 { font-size: 29px; font-weight: 750; letter-spacing: -.7px; line-height: 1.28; margin: 14px 0 0; }
.v2-home-sub { margin: 2px 0 0; font-size: 29px; font-weight: 750; letter-spacing: -.7px; line-height: 1.28; color: var(--muted-2); }
.v2-launch { position: relative; margin-top: 26px; border: 1px solid var(--line-net); border-radius: 18px; background: var(--bg);
  box-shadow: 0 1px 2px rgba(var(--shadow-ink), .04), 0 14px 40px -24px rgba(var(--shadow-ink), .16); padding: 16px 16px 12px; }
.v2-launch:focus-within { border-color: color-mix(in srgb, var(--blue) 55%, var(--line-net)); box-shadow: 0 1px 2px rgba(var(--shadow-ink), .04), 0 14px 40px -22px rgba(45, 107, 240, .22); }
.v2-launch-in { display: block; width: 100%; resize: none; border: 0; outline: 0; background: transparent; font: inherit; font-size: 15.5px; line-height: 1.65; min-height: 56px; }
.v2-launch-in::placeholder { color: var(--muted-2); }
.v2-launch-in:disabled { opacity: .55; }
.v2-launch-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 10px; padding-top: 0; border-top: 0; }

.v2-launch-ctl { display: flex; align-items: center; flex-wrap: wrap; gap: 3px 6px; flex: 1; min-width: 0; }
.v2-launch-row > .v2-launch-send { align-self: flex-end; }
.v2-run { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; min-width: 0; }
.v2-run-sel { appearance: none; -webkit-appearance: none; height: 30px; padding: 0 18px 0 8px; border: 0; border-radius: 8px;
  background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5' viewBox='0 0 8 5'%3E%3Cpath d='M1 1l3 3 3-3' fill='none' stroke='%23A6B2C8' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat right 6px center;
  font: inherit; font-size: 12px; color: var(--muted); cursor: pointer; max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-run-sel:hover:not(:disabled) { color: var(--ink); background-color: var(--bg-tint); }
.v2-run-sel:disabled { opacity: .55; cursor: default; }
.v2-run-sel:focus-visible { outline: 2px solid var(--blue); outline-offset: -1px; }

/* 컴포저 첨부(#1870) — [＋] 파일 첨부 버튼 + 카드 드롭 하이라이트. 칩 줄(.pn-att)은 42-v2-panes.css 의 것을
   홈·프로젝트 칸이 같이 쓴다(같은 페이지에 둘 다 로드 — index.html). */
.v2-launch-att { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px;
  border: 1px solid var(--line-net); border-radius: 9px; background: transparent; color: var(--muted); font-size: 17px; line-height: 1; cursor: pointer; }
.v2-launch-att:hover { color: var(--ink); background: var(--bg-tint); }
.v2-launch-att:focus-visible { outline: 2px solid var(--blue); outline-offset: -1px; }
/* ctl 이 좁아 두 줄로 접힐 때도 [＋] 는 [시키기]와 같은 아랫줄에 — 둘 다 줄의 고정 모서리다. */
.v2-launch-row > .v2-launch-att { align-self: flex-end; }
.v2-launch.drop-active { outline: 2px dashed var(--blue); outline-offset: -6px; }
.v2-launch-send { flex: none; display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 16px; border-radius: 11px; font-weight: 650; }
.v2-launch-send kbd { font-family: var(--mono, ui-monospace, monospace); font-size: 10.5px; opacity: .7; font-weight: 400; }
.v2-launch-hint { display: none; }   /* Enter 안내 줄 폐지 — placeholder 와 관례가 이미 말한다(#1756) */
/* 프로젝트 연결 드롭다운(#1749) — 여는 자리는 [⋯ ▸ 이 세션] 이다(머리줄 칩은 2026-08-20 폐지).
   드롭다운 본체(.v2-pjpick)는 그대로 anchoredPopover .dash-pop 위에 얹힌다. */
.v2-pjpick { width: 320px; max-width: calc(100vw - 24px); display: flex; flex-direction: column; gap: 8px; padding: 8px; }   /* 배경·그림자는 .dash-pop-panel(20-dashboard.css) */
.v2-pjpick-in { height: 32px; border: 1px solid var(--line-net); border-radius: 8px; padding: 0 10px; font: inherit; font-size: 13px;
  background: var(--bg); color: var(--ink); }
.v2-pjpick-in:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; border-color: transparent; }
.v2-pjpick-list { max-height: 320px; overflow: auto; display: flex; flex-direction: column; }
.v2-pjpick-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; width: 100%; text-align: left; border: 0; background: none;
  padding: 7px 8px; border-radius: 8px; cursor: pointer; font: inherit; color: var(--ink); }
.v2-pjpick-row:hover { background: var(--bg-tint); }
.v2-pjpick-row .n { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 600; }
.v2-pjpick-row .m { flex: none; display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--muted); }
.v2-pjpick-row.cur { cursor: default; background: var(--code-surface); }
.v2-pjpick-cur { color: var(--mint-deep); font-weight: 700; }
.v2-pjpick-done { border: 1px solid var(--line-row); border-radius: 999px; padding: 0 6px; font-size: 10.5px; }
.v2-pjpick-none .n { color: var(--coral-text); }
.v2-pjpick-note:empty { display: none; }
.v2-liv-tag { display: inline-flex; align-items: center; gap: 7px; color: var(--mint-deep); font-weight: 800; font-size: 13px; }
.v2-h1 { margin: 10px 0 0; font-size: 22px; font-weight: 800; letter-spacing: -.45px; line-height: 1.38; text-wrap: balance; word-break: keep-all; }
.v2-title, .v2-desc { word-break: keep-all; }
/* 전폭 문서 칸 — 목록형 화면(연결)은 v2-center 의 읽기 폭(820px)을 쓰면 좌우가 200px 넘게 놀고
   그만큼 세로로 길어진다(실측 1440 창: 가운데 칸 1032 · 내용 820 · 좌우 106씩 · 세로 1.43배 스크롤).
   글을 읽는 화면이 아니라 **고르는 화면**이라 가로를 다 쓰고 세로를 줄이는 쪽이 맞다(원준 2026-08-20). */
.v2-wide { width: 100%; max-width: 1360px; margin: 0 auto; padding: 26px 32px 34px; }
@media (max-width: 900px) { .v2-wide { padding: 18px 16px 26px; } }

/* ══ 외부 앱 연결(#/connect · #/connect/<key>) — #1719 원준 ══════════════════════
   목록은 세션 트리와 같은 '행' 문법(아이콘 · 이름+메타 · 오른쪽 ›), 상세는 v2-center 문서 문법.
   새 시각 언어를 만들지 않는다 — 셸 안에서 화면마다 다른 결이 생기면 그게 '정리 안 된 느낌'의 뿌리다. */
.cn-top { display: flex; align-items: center; gap: 16px; margin: 18px 0 4px; flex-wrap: wrap; }
.cn-sum { display: flex; align-items: center; gap: 18px; flex: 1; min-width: 0; }
.cn-sum-i { display: inline-flex; align-items: baseline; gap: 6px; font-size: 12.5px; color: var(--muted); }
.cn-sum-i b { font-size: 19px; font-weight: 800; color: var(--ink); font-variant-numeric: tabular-nums; }
.cn-sum-i.on b { color: var(--mint-deep); }
.cn-find { flex: none; width: 220px; max-width: 100%; padding: 7px 11px; border: 1px solid var(--line-net); border-radius: 8px; background: var(--bg); font: inherit; font-size: 13px; color: var(--ink); }
.cn-find:focus { outline: 2px solid var(--blue); outline-offset: 1px; }
.cn-groups { display: flex; flex-direction: column; gap: 20px; margin-top: 16px; }
.cn-group-h { display: flex; align-items: baseline; gap: 10px; margin-bottom: 6px; flex-wrap: wrap; }
.cn-group-note { font-size: 12px; color: var(--muted); }
/* ★격자 — 앱은 '읽는 것'이 아니라 '고르는 것'이라 한 줄씩 쌓을 이유가 없다. 폭에 따라 접힌다(실측:
   1920→4열 · 1440→3열 · 1280/900→2열 · 430→1열). 13개가 6줄로 끝난다(종전 13줄). */
.cn-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); gap: 4px 10px; }
.cn-row { display: flex; align-items: center; gap: 11px; width: 100%; padding: 9px 11px; border: 0; border-radius: 10px; background: none; font: inherit; text-align: left; text-decoration: none; color: inherit; cursor: pointer; }
.cn-row:hover { background: var(--bg-tint); }
.cn-row.blocked { cursor: pointer; }
.cn-row.blocked .cn-row-main .t { color: var(--ink-sub); }
.cn-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.cn-row-main .t { display: flex; align-items: center; gap: 7px; font-size: 14px; font-weight: 650; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cn-row-main .m { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cn-row-go { flex: none; color: var(--muted-2); font-size: 15px; }
.cn-row:hover .cn-row-go { color: var(--blue); }
.cn-dot { width: 6px; height: 6px; border-radius: 50%; flex: none; background: transparent; box-shadow: inset 0 0 0 1.5px var(--muted-2); }
.cn-dot.on { background: var(--mint-deep); box-shadow: 0 0 0 2.5px color-mix(in srgb, var(--mint-deep) 22%, transparent); }
.cn-extra { margin-top: 4px; padding-top: 18px; border-top: 1px solid var(--line-net); }
.cn-git-ic { width: 40px; height: 40px; flex: none; border-radius: 12px; background: var(--bg-tint-2); color: var(--muted); display: inline-grid; place-items: center; font-family: var(--mono, ui-monospace, monospace); font-size: 14px; font-weight: 700; }
/* 상세 */
.cn-back { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--muted); text-decoration: none; }
.cn-back:hover { color: var(--blue); }
.cn-head { display: flex; align-items: center; gap: 14px; margin-top: 14px; }
.v2-connect-app .v2-desc, .v2-connect .v2-desc { max-width: 72ch; }
.cn-head-tt { min-width: 0; }
.cn-head-tt .v2-title { margin: 0; }
.cn-head-st { display: flex; align-items: center; gap: 6px; margin-top: 3px; font-size: 12.5px; color: var(--muted); }
.cn-head-st.on { color: var(--mint-deep); font-weight: 600; }
.cn-acts { display: flex; align-items: center; gap: 10px; margin-top: 18px; flex-wrap: wrap; }
.cn-facts { display: grid; grid-template-columns: auto 1fr; gap: 7px 18px; margin: 0; padding: 14px 16px; border: 1px solid var(--line-net); border-radius: 12px; font-size: 13px; }
.cn-facts dt { color: var(--muted); }
.cn-facts dd { margin: 0; color: var(--ink); }
/* 상세의 아래 절반 — 넓으면 두 칸(사실·발급방법 | 설정), 좁으면 한 칸. 세로로만 쌓으면 슬랙처럼 설정이
   긴 앱은 사실 표가 화면 밖으로 밀린다. */
.cn-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: 24px; margin-top: 22px; align-items: start; }
@media (min-width: 1100px) { .cn-body:has(.cn-col + .cn-col) { grid-template-columns: minmax(320px, 0.9fr) minmax(0, 1.1fr); gap: 30px; } }
.cn-col { min-width: 0; display: flex; flex-direction: column; }
.cn-col > .cn-facts { margin-top: 0; }
.cn-col > .cn-sec:first-child { margin-top: 0; }
.cn-sec { margin-top: 24px; }
.cn-sec-h { margin-bottom: 8px; }
.cn-help { margin: 0 0 10px; font-size: 13.5px; color: var(--ink-sub); line-height: 1.7; max-width: 66ch; }
/* 연결 카드 안 소형 폼(#1881 노션 직결 client 2칸) — 입력·버튼을 세로로 좁게 쌓는다. */
.cn-sec-form { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; max-width: 420px; margin-top: 6px; }
.cn-sec-form input { width: 100%; }
/* 슬랙 대화 정책은 관리탭 카드 문법으로 만들어졌다 — 셸 안에서는 테두리 한 겹만 두르고 그대로 싣는다. */
.cn-slack { padding: 16px; border: 1px solid var(--line-net); border-radius: 12px; }
.cn-slack .card { border: 0; padding: 0; background: none; box-shadow: none; }
/* 확인할 것(#/inbox) — 홈의 v2-now 문법을 그대로 쓴다(새 시각 언어 금지). */
.v2-inbox .v2-now { margin-top: 26px; }
.v2-inbox-empty { margin-top: 40px; padding: 26px; border: 1px dashed var(--line-net); border-radius: 14px; text-align: center; }
.v2-inbox-empty .h { margin: 0; font-size: 15px; font-weight: 700; color: var(--ink); }
.v2-inbox-empty .sub { margin: 6px 0 0; font-size: 13px; color: var(--muted); }
.v2-find { padding: 4px var(--side-x, 8px) 2px; }
.v2-find-in { width: 100%; height: var(--row-h, 34px); border: 1px solid var(--line); border-radius: 9px; padding: 0 11px; font: inherit; font-size: 13px; background: var(--bg); }
.v2-find-in:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; border-color: transparent; }
.v2-sugs { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 12px; }
.v2-sugs .chip { font-size: 13px; padding: 6px 12px; border-radius: 999px; }
.v2-chat { flex: 1; min-height: 260px; border: 1px solid var(--line); border-radius: 14px; background: var(--bg); overflow: hidden; display: flex; flex-direction: column; }
.v2-chat-body { flex: 1; min-height: 0; display: flex; }
.v2-askdock { flex: none; margin-top: 0; padding: 10px 16px 0; }
/* 지금 도는 세션 — 두 결(#1756): 답 기다림은 앰버 카드(내가 풀어야 도는 일), 나머지는 조용한 목록.
   행 문법: 점 · [제목+프로젝트 한 덩어리] · 상태시각. 여섯 요소가 같은 무게로 나열되던 것을 셋으로 줄였다. */
.v2-now { margin-top: 34px; display: flex; flex-direction: column; gap: 22px; }
.v2-now .v2-k { display: block; margin-bottom: 4px; }
.v2-now-h { display: flex; align-items: baseline; justify-content: space-between; }
.v2-now .v2-k.wait { color: var(--warn-deep); }
.v2-now-wait { border: 1px solid color-mix(in srgb, var(--warn-deep) 26%, transparent); background: color-mix(in srgb, var(--warn-deep) 5%, var(--bg)); border-radius: 14px; padding: 12px 12px 6px; }
.v2-now-row { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 9px; text-decoration: none; color: inherit; }
.v2-now-row:hover { background: var(--bg-tint); }
.v2-now-wait .v2-now-row:hover { background: color-mix(in srgb, var(--warn-deep) 8%, var(--bg)); }
.v2-now-row + .v2-now-row { border-top: 0; }
.v2-now-row .tw { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 8px; }
.v2-now-row .t { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13.5px; font-weight: 650; color: var(--ink); }
.v2-now-row .p { font-size: 11.5px; color: var(--muted-2); flex: none; max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-now-row .st { font-size: 12px; color: var(--muted); flex: none; font-variant-numeric: tabular-nums; }
.v2-now-row .go { flex: none; }
/* 홈 '이어서 할 수 있어요'(#1808) — 도는 세션 아래, 가는 선 하나로 갈라 둔 조용한 묶음. */
.v2-now-past { border-top: 1px solid var(--line-net); padding-top: 16px; }
.v2-now-past .v2-now-row .t { font-weight: 550; }

/* 리브 페이지(클래식 renderLiv 를 이 칸에) — 35-liv 의 body[data-route=liv] main 규칙은 여기 안 닿는다(main 태그 안 씀) */
/* 리브도 다른 중앙 화면과 같은 흰 판(#1756) — 리브만 회색이면 3열 셸에서 그 화면만 딴 세계로 읽힌다.
   카드·대화창은 자체 테두리가 있어 흰 판 위에서도 경계가 산다(35-liv.css .liv-card/.liv-chat). */
.v2-livpage { flex: 1; min-height: 0; padding: 14px 18px 16px; background: var(--bg); display: flex; flex-direction: column; }
.v2-livpage .liv-wrap { flex: 1; }
body[data-ui="v2"][data-route="liv"] { overflow: hidden; }

/* 앱 프레임 — 클래식 화면 임베드 · 라이브 터미널 */
.v2-app { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.v2-frame-h { display: flex; align-items: center; gap: 10px; padding: 8px 14px; border-bottom: 1px solid var(--line); background: var(--bg); }
.v2-frame-t { font-size: 13.5px; font-weight: 800; }
.v2-frame-sub { font-size: 12px; color: var(--muted); }
.v2-frame-acts { margin-left: auto; display: inline-flex; gap: 8px; align-items: center; }
.v2-frame-acts .btn-text { font-size: 12.5px; }
.v2-sess-meta { display: flex; align-items: center; gap: 8px; padding: 6px 14px; font-size: 12.5px; color: var(--ink-sub); border-bottom: 1px solid var(--line-row); background: var(--bg); }
.v2-sess-meta a { color: var(--ink-sub); text-decoration: none; }
.v2-sess-meta a:hover { color: var(--blue); }
.v2-frame { flex: 1; min-height: 0; width: 100%; border: 0; background: var(--bg); }

/* ── 브라우저 서피스(#1829, web/v2/browser-surface.ts) ──
   남의 웹을 화면 한 칸에서 본다. 골격은 앱 프레임(.v2-app)과 같다: 머리 한 줄 고정 → 본문이 남는 높이를 다 먹는다.
   머리가 .v2-frame-h 와 다른 이유는 여기 머리가 '이름표'가 아니라 **조작부**(주소·이동)이기 때문이다 — 입력칸 높이에 맞춘다. */
.v2-bs-bar { display: flex; align-items: center; gap: 8px; padding: 7px 12px; border-bottom: 1px solid var(--line); background: var(--bg); }
.v2-bs-navs { display: inline-flex; gap: 2px; }
.v2-bs-btn { width: 28px; height: 28px; display: grid; place-items: center; border: 0; border-radius: 7px; background: none; font: inherit; font-size: 16px; line-height: 1; color: var(--ink-sub); cursor: pointer; }
.v2-bs-btn:hover:not(:disabled) { background: var(--bg-tint); color: var(--ink); }
.v2-bs-btn:disabled { color: var(--muted-2); cursor: default; }
.v2-bs-addr { flex: 1; min-width: 0; height: 28px; padding: 0 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--bg); font: inherit; font-size: 12.5px; color: var(--ink); }
.v2-bs-addr:focus { outline: none; border-color: var(--blue); }
.v2-bs-acts { display: inline-flex; gap: 8px; align-items: center; }
.v2-bs-acts .btn-text { font-size: 12.5px; white-space: nowrap; }
.v2-bs-body { flex: 1; min-height: 0; display: flex; }
/* webview 는 교체 요소라 flex 자식으로 두면 내재 크기로 버틴다 — 명시적으로 남는 자리를 채우게 한다. */
.v2-bs-view { flex: 1; min-width: 0; min-height: 0; width: 100%; border: 0; background: var(--bg); }
/* 폴백(브라우저에서 연 웹 UI) — 오류 화면이 아니라 안내다. 가운데 좁은 단으로 두어 '읽을 것'으로 보이게 한다. */
.v2-bs-fallback { margin: auto; max-width: 420px; padding: 32px 24px; text-align: center; display: flex; flex-direction: column; gap: 10px; align-items: center; }
.v2-bs-fb-h { margin: 0; font-size: 14px; font-weight: 800; color: var(--ink); }
.v2-bs-fb-p { margin: 0; font-size: 12.5px; line-height: 1.6; color: var(--ink-sub); }
.v2-bs-fallback .btn { margin-top: 6px; }
/* 확장(애드온) 팝오버 — 앵커 팝오버(.dash-pop) 위에 얹는 목록. 행은 이름 + 제거 한 쌍뿐이다. */
.v2-bs-ext { display: flex; flex-direction: column; gap: 8px; min-width: 260px; padding: 4px 2px; }
.v2-bs-ext-h { margin: 0; font-size: 12px; font-weight: 800; color: var(--muted); letter-spacing: .02em; }
.v2-bs-ext-p { margin: 0; font-size: 12.5px; line-height: 1.6; color: var(--ink-sub); }
.v2-bs-ext-row { display: flex; align-items: center; gap: 10px; }
.v2-bs-ext-nm { flex: 1; min-width: 0; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── 우측 ── */
/* 우패널은 사이드바가 아니라 **가운데 화면의 연장**이다(#1756, 상민님). 종전엔 좌·우가 같은 회색 판(canvas)이라
   3열이 [탐색 | 내용 | 탐색] 으로 읽혔다. 우패널이 말하는 것은 탐색이 아니라 지금 보고 있는 것의 내용이므로 판을 가운데에 붙인다.
   잇는 것은 배경색만이 아니라 **구조선**이다:
     (1) 판을 같게(흰 바탕) — 회색 canvas 는 왼쪽 탐색열만의 것이 된다.
     (2) 두 열의 머리(가운데 .sc-head · 여기 .v2-aside-h)를 같은 38px·같은 아래선으로 맞춰 **한 줄로 잇는다**.
     (3) 골격도 같게 — 머리 고정 → 사실 한 줄 → 본문만 스크롤(가운데 sc-head → sc-chat 과 같은 리듬).
   사이의 세로 경계선은 **남긴다**(상민님: 2열 3열 사이에도 경계선이 없으면 이상하다) — 다만 판이 같으므로
   그 선은 이제 다른 판의 시작이 아니라 한 판 안의 칸막이로 읽힌다. */
.v2-aside { background: var(--bg); border-left: 1px solid var(--line); min-height: 0; overflow: hidden; padding: 0; display: flex; flex-direction: column; }
.v2-aside > .v2-empty { padding: 14px 16px; }
/* 우패널은 칸을 **갈아 낀다**(타임라인 ↔ 파일 탐색기, #1744) — 지우지 않고 숨긴다(발자취에 쌓인 것이 살아 있어야 한다).
   display 를 가진 자식은 [hidden] 만으로 안 사라지므로 여기서 못박는다. */
.v2-aside-pane > [hidden] { display: none !important; }
.v2-aside-h { display: flex; align-items: center; gap: 8px; flex: none; min-height: 38px; padding: 9px 16px 8px; border-bottom: 1px solid var(--line); }
.v2-aside-h b { font-size: 13.5px; font-weight: 800; }
.v2-aside-h .v2-k { margin-left: auto; font-variant-numeric: tabular-nums; }
.v2-liv-cards { gap: 6px; padding: 0 16px; }
.v2-liv-rail { overflow: visible; }
.v2-liv-rail .liv-cards { gap: 6px; }
.v2-kn-sec .v2-k { display: block; margin: 6px 2px 6px; }
.v2-kn-list { display: flex; flex-direction: column; gap: 6px; }
.v2-kn { display: flex; align-items: baseline; gap: 8px; background: var(--bg); border: 1px solid var(--line); border-radius: 10px; padding: 8px 10px; text-decoration: none; color: inherit; }
.v2-kn:hover { border-color: var(--line-net-2); }
.v2-kn-rel { font-family: var(--mono, ui-monospace, monospace); font-size: 10.5px; letter-spacing: .04em; flex: none; }
.v2-kn-rel.req { color: var(--ink-note); }
.v2-kn-rel.prod { color: var(--mint-deep); }
.v2-kn-name { font-size: 12.5px; font-weight: 600; color: var(--ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-applist { display: flex; flex-direction: column; gap: 4px; }
.v2-applink { display: flex; align-items: center; gap: 8px; padding: 7px 9px; border-radius: 8px; font-size: 13px; font-weight: 600; color: var(--ink); text-decoration: none; }
.v2-applink:hover { background: var(--bg-tint); }
.v2-facts { display: grid; grid-template-columns: auto 1fr; gap: 6px 12px; margin: 0; font-size: 12.5px; }
.v2-facts dt { color: var(--muted); }
.v2-facts dd { margin: 0; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── 우패널 파일 탐색기(#1744, web/v2/files.ts) ──
   세션 작업 폴더를 타임라인과 **같은 골격**으로 본다: 머리 고정 → 경로 한 줄 → 본문만 스크롤.
   종전엔 터미널 단독 페이지 왼쪽에 붙어 있었는데, 상단바를 합치며 이 자리로 왔다(가운데는 대화·터미널만 남는다). */
.v2-files { display: flex; flex-direction: column; flex: 1; min-height: 0; position: relative; }
.v2-files.fx-drag::after { content: '여기에 놓으면 이 폴더로 올라갑니다'; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  display: grid; place-items: center; text-align: center; padding: 0 18px; font-size: 12.5px; font-weight: 600; color: var(--blue);
  background: color-mix(in srgb, var(--blue) 8%, var(--bg)); border: 2px dashed var(--blue); border-radius: 10px; }
.fx-head .fx-scope { font-size: 12px; color: var(--muted); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fx-hacts { margin-left: auto; display: inline-flex; align-items: center; gap: 2px; flex: none; }
.fx-hbtn { border: 0; background: none; font: inherit; font-size: 12px; color: var(--ink-sub); padding: 3px 7px; border-radius: 6px; cursor: pointer; text-decoration: none; white-space: nowrap; }
.fx-hbtn:hover { background: var(--bg-tint); color: var(--ink); }
.fx-path { flex: none; display: flex; align-items: center; flex-wrap: wrap; gap: 1px; padding: 7px 14px; border-bottom: 1px solid var(--line-row); }
.fx-crumb { border: 0; background: none; font: inherit; font-family: var(--mono, ui-monospace, monospace); font-size: 11.5px; color: var(--muted); padding: 1px 4px; border-radius: 5px; cursor: pointer; }
.fx-crumb:hover { color: var(--blue); background: var(--bg-tint); }
.fx-crumb-sep { font-size: 10px; color: var(--muted-2); }
/* 심링크를 타고 들어와 있으면 '진짜 어디인지'를 말한다 — 안 그러면 그 내용이 세션 폴더 안에 있는 줄 안다. */
.fx-linknote { flex: none; display: flex; align-items: center; gap: 6px; padding: 6px 14px; font-size: 11px; color: var(--muted);
  border-bottom: 1px solid var(--line-row); background: var(--bg-tint); overflow: hidden; }
.fx-linknote[hidden] { display: none; }
.fx-linknote .mono { font-family: var(--mono, ui-monospace, monospace); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; direction: rtl; text-align: left; }
.fx-link-ic { flex: none; color: var(--blue); }
.fx-scroll { flex: 1; min-height: 0; overflow: auto; padding: 6px 8px 18px; }
.fx-list { display: flex; flex-direction: column; }
/* 한 줄 = [열기 버튼(아이콘·이름·크기)] + [액션들] — 버튼 안에 버튼을 넣지 않으려고 둘로 나눈다(키보드로도 닿는다). */
.fx-row { display: flex; align-items: center; gap: 2px; border-radius: 7px; }
.fx-row:hover { background: var(--bg-tint); }
.fx-open { flex: 1; min-width: 0; display: flex; align-items: center; gap: 7px; padding: 5px 6px; border: 0; background: none; font: inherit; font-size: 12.5px; color: var(--ink); text-align: left; cursor: pointer; }
.fx-ic { flex: none; width: 16px; text-align: center; opacity: .85; }
.fx-nm { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fx-row.is-link .fx-nm { color: var(--ink-note); }
.fx-link { flex: none; font-size: 10.5px; color: var(--blue); }
.fx-sz { margin-left: auto; flex: none; font-family: var(--mono, ui-monospace, monospace); font-size: 10.5px; color: var(--muted-2); }
.fx-acts { flex: none; display: inline-flex; align-items: center; gap: 2px; padding-right: 4px; opacity: 0; }
.fx-row:hover .fx-acts, .fx-row:focus-within .fx-acts { opacity: 1; }
.fx-act { display: inline-grid; place-items: center; width: 20px; height: 20px; border: 0; background: none; border-radius: 5px; font: inherit; font-size: 11px; color: var(--muted); cursor: pointer; }
.fx-act:hover { background: var(--bg-punch); color: var(--ink); }
.fx-act svg { width: 13px; height: 13px; }
/* 미리보기 — 목록 자리에 제자리 전환(대시보드 폴더 위젯과 같은 문법). 정독·공유는 [⛶] 전체페이지가 맡는다. */
.fx-pbar { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; padding: 0 0 8px; border-bottom: 1px solid var(--line-row); }
.fx-pname { font-size: 12px; font-weight: 700; color: var(--ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fx-pstage { padding: 10px 2px 0; }
.fx-p-img { max-width: 100%; height: auto; border-radius: 8px; }
.fx-p-pdf { width: 100%; height: 62vh; border: 1px solid var(--line); border-radius: 8px; }
.fx-p-md { font-size: 13px; line-height: 1.65; }
.fx-p-code { font-size: 11.5px; line-height: 1.55; overflow: auto; }
.fx-p-table { overflow: auto; }
.fx-p-audio, .fx-p-video { width: 100%; }
.fx-p-msg { font-size: 12.5px; color: var(--muted); line-height: 1.6; }

/* ── 우패널 타임라인(#1719) — 프로젝트·세션·워크스페이스가 같은 부품 ──
   상민님 2026-08-18: "중요한 결과·산출물만. 한 줄로 요약하고 자세한 건 눌러서.
   근데 글자가 다다다닥 붙어 있으니 뭔 소린지 못 알아듣겠다 — 차라리 이전이 나았다."
   → 한 줄 규칙은 지키되 **줄끼리 숨 쉬게** 한다: 행 높이·글자 크기를 올리고(사이드바 14px 기준),
     항목 사이를 띄우고, 장은 카드처럼 바탕을 준다. 필터 줄은 없다(애초에 남은 것만 싣는다). */
.tl-wrap { display: flex; flex-direction: column; flex: 1; min-height: 0; }
/* 머리 아래 한 줄 — 이 화면이 무엇을 보고 있는지의 사실(세션 상태·프로젝트·하네스). 가운데 대화창 머리와 같은 정보 층. */
.tl-facts { flex: none; padding: 8px 16px; border-bottom: 1px solid var(--line-row); }
.tl-facts[hidden] { display: none; }
.tl-scroll { flex: 1; min-height: 0; overflow: auto; padding: 10px 16px 22px; }
/* 무게가 낮아 접어 둔 것 — 지운 게 아니라 접었다는 표시(#1756). */
.tl-rest { display: flex; align-items: center; gap: 6px; width: 100%; margin: 8px 0 0; padding: 7px 10px 7px 60px; border: 0; border-radius: 8px;
  background: none; font: inherit; font-size: 11.5px; color: var(--muted); cursor: pointer; text-align: left; }
.tl-rest:hover { color: var(--ink); background: var(--bg-tint); }
.tl-scope { flex: 1; min-width: 0; font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 보는 차례 스위치(#1819) — 머리 바의 조용한 고스트 버튼. 개수(.v2-k)는 늘 맨 오른쪽에 있던 자리를
   지키고, 스위치가 그 왼쪽에 붙는다(사람이 이미 아는 자리를 밀어내지 않는다). */
.tl-ord { flex: none; display: inline-flex; align-items: center; gap: 4px; padding: 3px 7px; border: 0; border-radius: 7px;
  background: none; font: inherit; font-size: 11px; font-weight: 600; color: var(--muted); cursor: pointer; white-space: nowrap; }
.tl-ord:hover { color: var(--ink); background: var(--bg-tint); }
.tl-ord:focus-visible { outline: 2px solid var(--blue); outline-offset: -1px; }
.tl-ord-i { font-size: 10.5px; line-height: 1; color: var(--muted-3); }
.tl-ord:hover .tl-ord-i { color: var(--blue); }
.tl-wrap .v2-aside-h .tl-ord { margin-left: auto; }
.tl-wrap .v2-aside-h .tl-ord + .v2-k { margin-left: 0; }
.tl-cmp[hidden] { display: none; }
/* 간단히에서 접힌 '남은 것'의 표 — 답 줄 끝에 붙는 아주 작은 칩. 접었다는 사실과 몇 개인지를 한 자리에서 말한다
   (결과물 보기의 접힘 줄과 같은 규약: 안 보이는 것과 없는 것은 다르다). */
.tl-kidsn { flex: none; align-self: flex-start; margin-top: 1px; padding: 0 6px; border: 0; border-radius: 999px;
  background: var(--bg-tint-2); color: var(--muted); font: inherit; font-size: 10.5px; font-weight: 700;
  font-variant-numeric: tabular-nums; line-height: 18px; cursor: pointer; }
.tl-kidsn:hover { color: var(--blue); }
.tl-kidsn:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }

/* ── 산출물 결과 줄(#1819 안 A · 원준 2026-08-24) ─────────────────────────────────
   "눌러서 따로 볼 수 있는 것이 나왔으면 타임라인에서도 눌리게, 눈에 잘 보이게."
   답 바로 아래 한 줄씩. 34px 타일(그림이면 진짜 축소본, 아니면 종류 아이콘) + 이름 + 열기.
   ⚠ '간단히'로 접어도 이 줄은 남는다 — 접는 것은 과정이지 결과가 아니다.
   색은 토큰 직참조(폴백 금지 — 폴백 불일치가 실버그를 만든 전례가 있다). */
.tl-outs { display: flex; flex-direction: column; gap: 6px; margin-top: 7px; }
.tl-out {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 7px 9px;
  border: 1px solid var(--line); border-radius: 9px; background: var(--bg);
  font: inherit; text-align: left; cursor: pointer;
}
.tl-out:hover { border-color: var(--blue); background: var(--bg-tint); }
.tl-out:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }
.tl-out-tile {
  flex: none; width: 34px; height: 34px; border-radius: 6px; background: var(--bg-tint-2);
  display: grid; place-items: center; color: var(--blue); overflow: hidden;
}
.tl-out-tile.img { background: var(--bg); border: 1px solid var(--line); }
.tl-out-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tl-out-meta { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.tl-out-meta b {
  font-size: 12.5px; font-weight: 600; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tl-out-meta span {
  font-family: var(--mono); font-size: 10px; letter-spacing: .05em; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tl-out-go { flex: none; display: grid; place-items: center; color: var(--muted-3); }
.tl-out:hover .tl-out-go { color: var(--blue); }
.tl-wrap .v2-aside-h .v2-k { margin-left: auto; }
.tl-list { display: flex; flex-direction: column; min-height: 0; gap: 2px; }
.tl-day { display: flex; align-items: center; gap: 10px; padding: 22px 2px 8px; font-size: 11px; font-weight: 700; letter-spacing: .04em; color: var(--muted-2); }
.tl-day:first-child { padding-top: 2px; }
.tl-day::after { content: ""; flex: 1; height: 1px; background: var(--line-row); }

/* 세로 레일 — 점이 레일 위에 얹힌다 */
/* 점과 선은 **한 좌표에서 파생**시킨다 — 따로 적어 두면 어느 한쪽만 고쳐져 어긋난다(실측: 선이 첫 점보다 2px 아래에서 시작).
   --tl-cx = 레일 기준 점 중심 x · --tl-cy = 카드 기준 점 중심 y(제목 첫 줄 한가운데) · --tl-pad = 본문 들여쓰기 */
.tl-rail { position: relative; --tl-pad: 0px; --tl-cx: 0px; --tl-cy: 0px; --tl-dot: 0px; display: flex; flex-direction: column; gap: 2px; }
.tl-card::after { content: none; }
.tl-card:first-child::after { content: none; }
.tl-card:last-child::after { content: none; }
/* 원장 행(#1756) — [시각·종류 거터 | 제목]. 색 축은 걷었다: 세로로 정렬된 모노 시각이 리듬을 만들고,
   변하는 정보(제목)만 잉크색이다. 오류만 코랄. */
.tl-card {
  position: relative; display: flex; flex-direction: row; align-items: flex-start; gap: 12px;
  background: none; border: 0; border-radius: 10px; padding: 8px 10px 8px 8px;
  text-decoration: none; color: inherit; transition: background .14s ease;
}
.tl-card + .tl-card { box-shadow: none; }
.tl-card::before { content: none; }
.tl-gut { flex: none; width: 40px; display: flex; flex-direction: column; align-items: flex-end; gap: 3px; padding-top: 2.5px; }
.tl-gut .tl-tm { font-size: 11px; letter-spacing: 0; }
.tl-kw { font-size: 10.5px; color: var(--muted-3); letter-spacing: .02em; }
.tl-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.tl-card.can { cursor: pointer; }
.tl-card.can:hover, .tl-card.go:hover { background: var(--bg-tint); }
.tl-card.open { background: var(--bg-tint); }
.tl-card:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }
.tl-head { display: flex; align-items: flex-start; gap: 8px; }
.tl-ttl {
  flex: 1; min-width: 0; font-size: 13px; line-height: 1.55; font-weight: 600; letter-spacing: -.1px;
  color: var(--ink); word-break: keep-all;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.tl-head .tl-tm { flex: none; padding-top: 2px; }
.tl-tm { font-family: var(--mono, ui-monospace, monospace); font-size: 10.5px; color: var(--muted-2); letter-spacing: -.2px; }
.tl-head .tl-face { margin-top: 1px; }
.tl-meta { display: none; }
.tl-what { min-width: 0; }
.tl-who { flex: none; }
.tl-car { flex: none; color: var(--muted-3); font-size: 13px; line-height: 1.4; transition: transform .16s ease, color .16s ease; }
.tl-card.can:hover .tl-car { color: var(--blue); }
.tl-card.open .tl-car { transform: rotate(90deg); color: var(--blue); }
.tl-x { flex: none; font-family: var(--mono, ui-monospace, monospace); font-size: 10.5px; color: var(--muted-2); padding-top: 3px; }
.tl-card.tlk-task::before, .tl-card.tlk-knowledge::before, .tl-card.tlk-file::before,
.tl-card.tlk-activity::before, .tl-card.tlk-cmd::before, .tl-card.tlk-project::before,
.tl-card.tlk-say::before, .tl-card.tlk-meta::before { content: none; }
/* ⚠ 아래는 옛 렌더러 시절 셀렉터 — 지금 안 붙지만 css-drops 게이트(HEAD 포함 검사) 때문에 남긴다. */
.tl-verb { flex: none; font-size: 11.5px; font-weight: 700; color: var(--muted); }
.tl-meta .tl-tm { margin-left: auto; }
.tl-more { flex: none; font-size: 11px; color: var(--muted-2); }
.tl-card.can:hover .tl-more { color: var(--blue); }
.tl-card.t1::before { content: none; }
.tl-card.t1.tlk-activity::before { content: none; }
.tl-card.tlk-project .tl-verb, .tl-card.tlk-knowledge .tl-verb, .tl-card .tl-verb,
.tl-card.tlk-activity .tl-verb, .tl-card.tlk-cmd .tl-verb, .tl-card.tlk-say .tl-verb, .tl-card.tlk-meta .tl-verb { color: var(--muted); }
.tl-card.tlk-meta .tl-ttl { color: var(--ink-sub); font-weight: 500; }
.tl-card.err .tl-ttl { color: var(--coral-text); }
.tl-body { display: flex; flex-direction: column; gap: 0; margin-top: 5px; padding-top: 6px; border-top: 1px solid var(--line-row); }
.tl-sub { display: flex; align-items: center; gap: 8px; min-height: 26px; padding: 2px; border-radius: 7px; text-decoration: none; color: inherit; }
.tl-sub.go:hover { background: var(--bg-tint-2); }
.tl-sub-v { flex: none; font-size: 11px; font-weight: 600; color: var(--muted-2); min-width: 30px; }
.tl-sub-v.tlk-knowledge, .tl-sub-v.tlk-file { color: var(--muted); }
.tl-sub-t { flex: 1; min-width: 0; font-size: 12.5px; color: var(--ink-sub); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tl-sub.go:hover .tl-sub-t { color: var(--blue); }

.tl-face { margin-left: auto; }
.tl-meta .tl-who + .tl-car, .tl-meta .tl-what + .tl-car { margin-left: auto; }
.tl-car { flex: none; color: var(--muted-3); font-size: 13px; line-height: 1; transition: transform .16s ease, color .16s ease; }
.tl-card.can:hover .tl-car { color: var(--blue); }
.tl-card.open .tl-car { transform: rotate(90deg); color: var(--blue); }
.tl-x { flex: none; font-family: var(--mono, ui-monospace, monospace); font-size: 10.5px; color: var(--muted-2); padding-top: 3px; }
.tl-card.tlk-task::before { background: var(--mint-deep); }
.tl-card.tlk-knowledge::before { background: var(--teal); }
.tl-card.tlk-file::before { background: var(--mint-deep); }
.tl-card.tlk-activity::before { background: var(--blue-fill); }
.tl-card.tlk-cmd::before { background: var(--bg); box-shadow: inset 0 0 0 1.5px var(--muted-2), 0 0 0 3px var(--bg); }
.tl-card.tlk-project::before { background: var(--blue-fill-deep); }
.tl-card.tlk-say::before, .tl-card.tlk-meta::before { background: var(--muted-3); }
/* ⚠ 아래 12줄은 main(#1756 이전 카드 디자인)에서 딸려온 죽은 규칙 — 지금 렌더러가 이 클래스를 붙이지 않는다.
   지우면 css-drops 게이트가 회귀로 잡으므로 다음 PR 에서 HEAD 정리와 함께 걷는다. */
.tl-verb { flex: none; font-size: 11.5px; font-weight: 700; color: var(--muted); }
.tl-meta .tl-tm { font-family: var(--mono, ui-monospace, monospace); font-size: 10.5px; color: var(--muted-2); margin-left: auto; }
.tl-more { flex: none; font-size: 11px; font-weight: 600; color: var(--muted-2); }
.tl-card.can:hover .tl-more { color: var(--blue); }
.tl-card.t1::before { background: var(--mint-deep); border-color: var(--mint-deep); }
.tl-card.t1.tlk-activity::before, .tl-card.t1.tlk-cmd::before, .tl-card.tlk-activity::before { background: var(--blue-fill); border-color: var(--blue); }
.tl-card.tlk-project .tl-verb { color: var(--blue-deep); }
.tl-card.tlk-knowledge .tl-verb { color: var(--teal); }
.tl-card.tlk-meta .tl-ttl { color: var(--ink-sub); font-weight: 500; }
.tl-card .tl-verb { color: var(--mint-deep); }
.tl-card.tlk-activity .tl-verb, .tl-card.tlk-cmd .tl-verb { color: var(--blue); }
.tl-card.tlk-say .tl-verb, .tl-card.tlk-meta .tl-verb { color: var(--muted); }
.tl-card.err .tl-ttl { color: var(--coral-text); }
.tl-body { display: flex; flex-direction: column; gap: 0; margin-top: 6px; padding-top: 8px; border-top: 1px solid var(--line-row); }
.tl-sub { display: flex; align-items: center; gap: 8px; min-height: 26px; padding: 2px; border-radius: 7px; text-decoration: none; color: inherit; }
.tl-sub.go:hover { background: var(--bg-tint-2); }
.tl-sub-v { flex: none; font-size: 11px; font-weight: 600; color: var(--muted-2); min-width: 30px; }
.tl-sub-v.tlk-knowledge { color: var(--teal); }
.tl-sub-v.tlk-file { color: var(--mint-deep); }
.tl-sub-t { flex: 1; min-width: 0; font-size: 12.5px; color: var(--ink-sub); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tl-sub.go:hover .tl-sub-t { color: var(--blue); }

.tl-face { width: 17px; height: 17px; border-radius: 50%; font-size: 9px; font-weight: 700; flex: none; display: inline-grid; place-items: center; color: var(--on-fill); overflow: hidden; }
.tl-face img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tl-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--muted-2); flex: none; display: inline-block; }
/* ⚠ 접두어 tlk- 인 이유: 옛 발자취 CSS 에 **범위 없는** .k-file/.k-task 규칙이 살아 있어(.k-task{background:coral})
   행에 k-task 를 붙이면 행 전체가 산호색으로 칠해진다(실측). 우리 클래스는 우리 접두어를 쓴다. */
.tl-dot.tlk-file { background: var(--mint-deep); }
.tl-dot.tlk-knowledge { background: var(--teal); }
.tl-dot.tlk-activity, .tl-dot.tlk-cmd { background: var(--blue-fill); }
.tl-dot.tlk-task, .tl-dot.tlk-project { background: var(--blue-fill-deep); }
.tl-dot.tlk-source { background: var(--node-blue-soft); }

/* ── 질문·대답(#1819 원준 2026-08-21) ───────────────────────────────────────────
   타임라인은 프로젝트가 아니라 **세션**의 위젯이다. 그래서 한 항목이 아니라 **한 묶음**이 단위다:
   [질문] 내가 시킨 것 → [답] 그 답과 그때 남은 것. 묶음 안은 붙이고, 묶음끼리는 띄운다 —
   그 리듬만으로 "여기서부터 다른 얘기"가 읽히므로 구분선을 더 긋지 않는다.
   색은 전부 토큰이다(다크는 90-dark.css 가 같은 토큰을 갈아 끼운다 — 여기에 hex 를 박지 않는다). */
.tl-qa { display: flex; flex-direction: column; }
.tl-qa + .tl-qa { margin-top: 14px; }
.tl-qa .tl-card { padding-top: 6px; padding-bottom: 6px; }
/* 질문 — 잉크색 한 줄. 이 줄만 잉크고 나머지는 톤을 낮춰, 훑을 때 질문만 먼저 눈에 들어오게. */
.tl-q .tl-ttl { -webkit-line-clamp: 3; }
.tl-q .tl-kw { color: var(--muted-2); font-weight: 700; }
/* 답 — 질문 바로 아래 붙는다. 거터에 시각이 없으므로(같은 묶음이다) 종류 한 단어만 선다. */
.tl-a { padding-top: 0 !important; }
.tl-a .tl-gut { padding-top: 1px; }
.tl-a .tl-ans { font-weight: 500; color: var(--ink-sub); -webkit-line-clamp: 3; }
.tl-a.err .tl-ans { color: var(--coral-text); }
/* 붙여넣은 덩어리 — 제목으로 세우지 않고 크기만 말한다. 눌러야 전문이 나온다. */
.tl-paste { display: flex; margin: 1px 0 3px; }
.tl-paste span {
  display: inline-flex; align-items: center; max-width: 100%; padding: 1px 7px; border-radius: 999px;
  background: var(--bg-tint-2); color: var(--muted);
  font-size: 10.5px; font-weight: 700; letter-spacing: .01em; white-space: nowrap;
}
/* 지시 전문 — 접혀 있다가 눌러서. 원문 보관소가 아니라 확인용이라 높이를 묶어 둔다. */
.tl-full {
  margin: 6px 0 2px; padding: 8px 10px; max-height: 260px; overflow: auto;
  border-radius: 8px; background: var(--bg-tint);
  font-family: var(--mono, ui-monospace, monospace); font-size: 11px; line-height: 1.6;
  color: var(--ink-sub); white-space: pre-wrap; word-break: break-word;
}
.tl-full[hidden] { display: none; }
/* 그 지시에서 남은 것 — 답 밑에 조용히 붙는다(별도 상자를 세우지 않는다). */
.tl-kids { display: flex; flex-direction: column; gap: 0; margin-top: 2px; }
.tl-sub.err .tl-sub-t { color: var(--coral-text); }
.tl-dot.tlk-say, .tl-dot.tlk-meta { background: var(--muted-2); }
.tl-dot.tlk-all { background: transparent; box-shadow: inset 0 0 0 1.5px var(--muted-2); }
.v2-kn-foot { flex: none; margin-top: 0; padding: 14px 16px 18px; border-top: 1px solid var(--line); display: flex; flex-direction: column; gap: 7px; }

/* ── 런치패드 ── */
.v2-pad { position: fixed; inset: 0; z-index: 900; background: rgba(var(--tint-ink), .28); backdrop-filter: blur(11px); display: flex; flex-direction: column; align-items: center; padding: 48px 24px; overflow: auto; }
/* 스포트라이트식 검색 한 칸(#1841) — 제목·설명 줄·닫기 버튼을 걷어내고 칸 하나만 남긴다.
   흰 판이 아니라 뒤가 비치는 유리 — 흐린 배경 위에 얹힌 한 겹이라 아이콘들과 같은 언어를 쓴다. */
.v2-pad-field { width: min(560px, 100%); height: 58px; margin-bottom: 26px; display: flex; align-items: center; gap: 12px;
  padding: 0 16px; border-radius: 16px; background: var(--v2-pad-field); border: 1px solid var(--v2-pad-field-line);
  backdrop-filter: blur(24px) saturate(1.3); box-shadow: 0 16px 44px rgba(var(--shadow-ink), .16); }
.v2-pad-mag { width: 21px; height: 21px; flex: none; fill: none; stroke: var(--muted); stroke-width: 2; stroke-linecap: round; }
/* 칸 안에 테두리를 또 두르지 않는다 — 유리판 자체가 칸이다. 늘 포커스라 포커스 링도 두지 않는다. */
input.v2-pad-search { flex: 1; min-width: 0; height: 100%; border: 0; border-radius: 0; background: none; box-shadow: none; padding: 0; font: inherit; font-size: 19px; font-weight: 500; color: var(--ink); }
input.v2-pad-search:focus { outline: none; border: 0; background: none; box-shadow: none; }
input.v2-pad-search::placeholder { color: var(--muted); font-weight: 400; }
input.v2-pad-search::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.v2-pad-esc { flex: none; font: inherit; font-size: 10.5px; font-weight: 700; letter-spacing: .04em; color: var(--muted);
  background: rgba(var(--tint-ink), .07); border: 1px solid var(--v2-pad-field-line); border-radius: 6px; padding: 3px 7px; }
.v2-pad-grid { width: min(920px, 100%); display: grid; grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); gap: 6px; }
.v2-pad-item { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 14px 6px 12px; background: none; border: 0; border-radius: 18px; text-decoration: none; color: var(--ink); text-align: center; }
.v2-pad-item:hover { background: rgba(var(--tint-ink), .12); }
.v2-pad-grid--q .v2-pad-item:first-child { background: rgba(var(--tint-ink), .12); }
.v2-pad-item b { font-size: 12.5px; font-weight: 700; line-height: 1.35; }
.v2-pad-ico { width: 60px; height: 60px; display: grid; place-items: center; color: var(--ink-sub); }
.v2-pad-ico .v2-ic { width: 30px; height: 30px; }
/* 유리 앱 아이콘(#1841) — 런치패드의 배경·흐림은 그대로 두고, 카드/타일 크롬만 걷어 아이콘을 그대로 앉힌다.
   ⚠ 서리 **색**은 여기 color 로 준다: 서리의 옅은 기울기가 currentColor 를 쓰는데, 그건 그라디언트가
    얹힌 svg 자신의 color 를 보지 그 도형의 color 를 보지 않는다. 값은 90-dark.css 에서 뒤집힌다.
   ⚠ 그림자·글로우는 넣지 않는다 — 그게 '네온'이 된다(규칙 ④). */
.v2-gi { display: block; color: var(--v2-gi-frost); }
.v2-gi-frost { fill-opacity: var(--v2-gi-frost-a); }
.v2-gi-punch { fill: var(--v2-gi-punch); fill-opacity: var(--v2-gi-punch-a); }
/* 타일 배경이 없으니 유리 아이콘이 곧 타일이다 — 칸을 꽉 채운다. */
.v2-pad-ico .v2-gi { width: 60px; height: 60px; }
.v2-pad-empty { color: var(--on-fill); font-size: 13px; }
/* 세션 앱 타일(#1780) — 화면 앱과 성격이 다르다(열면 전용 AI 세션이 뜬다). 민트 강조 + 배지로 구분. */
.v2-pad-item--app { position: relative; cursor: pointer; font: inherit; }
.v2-pad-item--app:hover { background: rgba(var(--tint-ink), .12); }
.v2-pad-item--app .v2-pad-ico { color: var(--mint-deep); }
.v2-pad-badge { font-size: 9.5px; font-weight: 800; letter-spacing: .02em; color: var(--mint-deep); background: var(--bg-success); border: 1px solid var(--ok-line-2); border-radius: 999px; padding: 1px 7px; }

/* ── 앱 사용 동의 창(#1780 app-session) — 세션 앱을 처음 열 때 뜨는 권한 확인 모달 ── */
.v2-consent-ov { position: fixed; inset: 0; z-index: 90; display: grid; place-items: center; background: rgba(var(--shadow-ink), .32); padding: 20px; }
.v2-consent { width: min(440px, 100%); background: var(--bg); border: 1px solid var(--line); border-radius: 16px; box-shadow: var(--shadow-2, 0 8px 30px rgba(var(--shadow-ink), .14)); padding: 22px 22px 18px; }
.v2-consent-t { margin: 0 0 6px; font-size: 16px; font-weight: 800; color: var(--ink); line-height: 1.4; }
.v2-consent-sub { margin: 0 0 16px; font-size: 12.5px; color: var(--muted); line-height: 1.6; }
.v2-consent-grp { display: flex; gap: 10px; align-items: baseline; padding: 8px 0; border-top: 1px solid var(--line); }
.v2-consent-grp > b { flex: none; width: 44px; font-size: 12px; color: var(--ink-sub); }
.v2-consent-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.v2-consent-chip { font-family: var(--mono, ui-monospace, monospace); font-size: 11px; color: var(--blue); background: var(--bg-tint); border: 1px solid var(--line-net-2); border-radius: 7px; padding: 2px 8px; }
.v2-consent-chip.none { color: var(--muted); background: transparent; border-color: var(--line); font-family: inherit; }
.v2-consent-acts { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }

/* ── 앱 UI 창(#1780 PR5) — 설치된 앱의 UI 페이지를 샌드박스 iframe 으로 실는 모달 ── */
.v2-appui-ov { position: fixed; inset: 0; z-index: 88; display: grid; place-items: center; background: rgba(var(--shadow-ink), .36); padding: 24px; }
.v2-appui { width: min(960px, 100%); height: min(680px, 88vh); display: flex; flex-direction: column; background: var(--bg); border: 1px solid var(--line); border-radius: 16px; box-shadow: var(--shadow-2, 0 8px 30px rgba(var(--shadow-ink), .14)); overflow: hidden; }
.v2-appui-h { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--line); flex: none; }
.v2-appui-t { font-size: 14px; font-weight: 800; color: var(--ink); }
.v2-appui-badge { font-size: 9.5px; font-weight: 800; letter-spacing: .02em; color: var(--blue); background: var(--bg-tint); border: 1px solid var(--line-net-2); border-radius: 999px; padding: 1px 7px; }
.v2-appui-spacer { flex: 1; }
.v2-appui-frame { flex: 1; width: 100%; border: 0; background: var(--surface); }

/* ── worker 앱 실행 위치 선택·상태(#1780 Stage B) ── */
.v2-exec-ov { position: fixed; inset: 0; z-index: 91; display: grid; place-items: center; background: rgba(var(--shadow-ink), .34); padding: 20px; }
.v2-exec { width: min(520px, 100%); background: var(--bg); border: 1px solid var(--line); border-radius: 16px; box-shadow: var(--shadow-2, 0 8px 30px rgba(var(--shadow-ink), .14)); padding: 22px; }
.v2-exec h3 { margin: 0 0 6px; font-size: 16px; line-height: 1.45; color: var(--ink); }
.v2-exec > p { margin: 0 0 16px; color: var(--muted); font-size: 12.5px; line-height: 1.6; }
.v2-exec-list { display: grid; gap: 8px; max-height: min(380px, 52vh); overflow: auto; }
.v2-exec-opt { position: relative; display: grid; gap: 3px; width: 100%; padding: 12px 14px; text-align: left; border: 1px solid var(--line); border-radius: 10px; background: var(--surface); color: var(--ink); font: inherit; cursor: pointer; }
.v2-exec-opt:hover, .v2-exec-opt:focus-visible { border-color: var(--blue); background: var(--bg-tint); outline: none; }
.v2-exec-opt b { font-size: 13px; }
.v2-exec-opt span { font-size: 12px; color: var(--muted); }
.v2-exec-opt small { font: 10.5px/1.4 var(--mono, ui-monospace, monospace); color: var(--muted-2); }
.v2-exec-actions { display: flex; justify-content: flex-end; margin-top: 16px; }
.v2-worker-app { min-height: 0; height: 100%; display: flex; flex-direction: column; background: var(--surface); }
.v2-worker-bar { flex: none; min-height: 38px; display: flex; align-items: center; gap: 8px; padding: 6px 12px; border-bottom: 1px solid var(--line); background: var(--bg); }
.v2-worker-place { font-size: 11.5px; color: var(--ink-sub); }
.v2-worker-state { flex: none; font-size: 10.5px; font-weight: 800; border: 1px solid var(--ok-line-2); border-radius: 999px; padding: 1px 7px; color: var(--ok-ink); background: var(--ok-bg); }
.v2-worker-state.is-terminal { color: var(--danger-ink); border-color: var(--danger-line); background: var(--danger-bg-2); }
.v2-worker-detail { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; color: var(--muted); }
.v2-worker-spacer { flex: 1; }
.v2-worker-restart { flex: none; }
.v2-worker-app > .v2-appui-frame { min-height: 0; }

@media (max-width: 700px) {
  .v2-worker-detail { display: none; }
  .v2-worker-bar { padding-inline: 9px; }
}

/* ── 타임라인 서랍(#1719 바탕화면 방향 1차) ─────────────────────────────────
   맥 문법(알림 센터): 홈(바탕화면)의 타임라인은 상주 열이 아니라 '불러오는 것' — 우상단 버튼으로
   우측 위에 카드로 떠오르고, 밖 클릭·Esc·화면 이동이면 물러난다. 우패널이 있는 화면(프로젝트·세션·리브)에선
   이미 열려 있으니 버튼이 숨고, 앱 프레임(no-tl)은 타임라인 자체가 없어 버튼도 없다.
   ≤900px 모바일은 자기 서랍(m-aside, 파일 끝 블록)이 맡는다 — 이 블록은 데스크톱 전용. */
@media (min-width: 901px) {
  .v2-tl-btn { position: absolute; top: 7px; right: 8px; z-index: 30; display: inline-flex; align-items: center; gap: 6px; height: 27px; padding: 0 10px;
    border: 1px solid var(--line); border-radius: 8px; background: var(--bg); color: var(--muted);
    font: inherit; font-size: 12.5px; font-weight: 700; cursor: pointer; }
  .v2-tl-btn:hover { color: var(--ink); border-color: var(--muted-3); }
  .v2-tl-btn svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
  #v2-root:not(.no-aside) .v2-tl-btn, #v2-root.no-tl .v2-tl-btn { display: none; }
  #v2-root.no-aside:not(.no-tl) .v2-tabs { padding-right: 112px; }   /* 탭도 [모든 탭] 끝막이도 서랍 버튼 밑으로 안 숨게 */
  #v2-root.d-aside .v2-tl-btn { color: var(--ink); background: var(--canvas); }
  #v2-root.d-aside .v2-aside { display: flex; position: fixed; top: 44px; right: 10px; bottom: 10px; z-index: 45;
    width: clamp(300px, var(--v2-aside-w, 316px), 420px); border: 1px solid var(--line); border-radius: 14px; overflow: hidden;
    background: var(--bg); box-shadow: 0 24px 64px rgba(var(--shadow-ink), .22), 0 4px 14px rgba(var(--shadow-ink), .10);
    animation: v2-drawer-in .18s ease; }
}
@keyframes v2-drawer-in { from { opacity: 0; transform: translateY(-6px); } }
@media (prefers-reduced-motion: reduce) { #v2-root.d-aside .v2-aside { animation: none; } }

/* 901~1100px(작은 노트북 창·아이패드 가로) — 옆 두 칸을 좁힌다. ⚠ 열은 다섯(사이드바·손잡이·가운데·손잡이·우패널)이라 셋만 적으면
   가운데가 셋째 열(280px)에 앉고 우패널이 다음 줄로 떨어진다(1024px 실측 #1777 — 손잡이가 생기기 전 규칙이 남아 있었다).
   손잡이가 인라인 변수로 너비를 쥐므로 변수를 덮지 않고 min() 으로 상한만 건다(더 좁히는 건 여전히 된다). */
@media (max-width: 1100px) {
  #v2-root { grid-template-columns: min(var(--v2-side-w), 232px) 6px minmax(0, 1fr) 6px min(var(--v2-aside-w), 280px); }
  #v2-root.no-aside { grid-template-columns: min(var(--v2-side-w), 232px) 6px minmax(0, 1fr) 0 0; }
  /* 팝아웃 창은 열이 셋뿐이다(#1744) — 위 5열 규칙을 그대로 맞으면 가운데가 6px 손잡이 칸에 앉는다. */
  #v2-root.solo { grid-template-columns: minmax(0, 1fr) 6px min(var(--v2-aside-w), 280px); }
  #v2-root.solo.no-aside { grid-template-columns: minmax(0, 1fr) 0 0; }
  .v2-center { padding-left: 24px; padding-right: 24px; }
}
/* (≤900px 는 파일 끝 '모바일' 블록이 통째로 맡는다 — 종전의 '사이드바 220px + 우패널 숨김' 규칙은 #1777 에서 서랍 셸로 대체됐다.) */

/* ── 세션 우패널: 사실 한 줄 + 발자취(web/session-trail.ts) ── */
.v2-sfacts { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; font-size: 12px; color: var(--ink-sub); padding: 0; }
.v2-sfacts a { color: var(--ink-sub); text-decoration: none; } .v2-sfacts a:hover { color: var(--blue); }
.v2-sfacts .sep { color: var(--muted-2); }
.tr-wrap { display: flex; flex-direction: column; gap: 8px; min-height: 0; }
.tr-sub { font-size: 11.5px; color: var(--muted); }
.tr-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.tr-chip { display: inline-flex; align-items: center; gap: 5px; font: inherit; font-size: 11.5px; line-height: 1; padding: 5px 8px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--bg); color: var(--ink-sub); cursor: pointer; }
.tr-chip:hover { border-color: var(--line-net); color: var(--ink); }
.tr-chip.on { background: var(--ink); color: var(--bg); border-color: var(--ink); }
.tr-chip.on .tr-chip-dot { box-shadow: 0 0 0 1px var(--bg); }
.tr-chip-n { font-family: var(--mono, ui-monospace, monospace); font-size: 10.5px; opacity: .8; }
.tr-chip-dot, .tr-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; display: inline-block; background: var(--muted-2); }
.k-file { background: var(--ink-sub); } .k-knowledge { background: var(--blue-fill); } .k-activity { background: var(--mint-deep); }
.k-project { background: var(--teal); } .k-task { background: var(--coral); } .k-source { background: var(--node-blue-soft); }
.k-all { background: transparent; box-shadow: inset 0 0 0 1.5px var(--muted-2); }
.tr-list { display: flex; flex-direction: column; gap: 2px; }
.tr-row { border-radius: 8px; }
.tr-row.open { background: var(--bg); border: 1px solid var(--line); }
.tr-row[hidden] { display: none; }
.tr-head { display: flex; align-items: center; gap: 7px; width: 100%; text-align: left; font: inherit; font-size: 12.5px; line-height: 1.45;
  padding: 6px 8px; border: 0; border-radius: 8px; background: none; color: var(--ink); cursor: pointer; }
.tr-head:hover { background: var(--bg); }
.tr-row.open > .tr-head { border-radius: 8px 8px 0 0; }
.tr-verb { color: var(--ink-sub); flex: none; }
.tr-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; font-weight: 600; }
.tr-x { font-family: var(--mono, ui-monospace, monospace); font-size: 10.5px; color: var(--muted); flex: none; }
.tr-st { font-family: var(--mono, ui-monospace, monospace); font-size: 10.5px; color: var(--coral-text); flex: none; }
.tr-tm { font-family: var(--mono, ui-monospace, monospace); font-size: 10.5px; color: var(--muted-2); flex: none; }
.tr-body { padding: 4px 10px 10px; display: flex; flex-direction: column; gap: 8px; font-size: 12.5px; }
.tr-body[hidden] { display: none; }
.tr-loading { color: var(--muted); font-size: 12px; margin: 0; }
.tr-title { font-weight: 700; font-size: 13px; line-height: 1.5; }
.tr-kv, .tr-path { font-family: var(--mono, ui-monospace, monospace); font-size: 11px; color: var(--ink-sub); word-break: break-all; }
.tr-part { min-width: 0; }
.tr-cap { font-family: var(--mono, ui-monospace, monospace); font-size: 10px; letter-spacing: .04em; color: var(--muted); margin-bottom: 3px; }
.tr-pre { margin: 0; padding: 8px 10px; border-radius: 6px; background: var(--bg-tint); border: 1px solid var(--line);
  font-family: var(--mono, ui-monospace, monospace); font-size: 11px; line-height: 1.55; white-space: pre-wrap; word-break: break-word; max-height: 360px; overflow: auto; }
.tr-md { font-size: 12.5px; line-height: 1.7; max-height: 480px; overflow: auto; }
.tr-md .md > :first-child { margin-top: 0; }
.tr-body .btn { align-self: flex-start; }

/* ═══ 모바일(≤900px, #1777 — 상민님 2026-08-19 "모바일 화면 대응, 특히 세션뷰") ═══
   세 칸 그리드 → **1열 + 서랍 둘 + 상단 바 하나**. JS 짝: web/v2/mobile.ts(같은 문턱을 matchMedia 로 본다).
   문턱 900 = 종전에 우패널을 숨기던 그 문턱이다 — 폰(≤430)만이 아니라 태블릿 세로(768~834)도 여기 든다. 사이드바 220px 를 그리드에
   남기고 우패널을 숨기던 종전 태블릿 그림은, 대화창이 좁아지고 타임라인엔 닿을 길이 없었다. 서랍 둘이면 둘 다 산다.
   원칙: 기능을 숨기지 않는다(사이드바·우패널은 서랍으로 살아 있다) · 데스크톱(>900) 그림은 한 픽셀도 안 바뀐다(전부 미디어쿼리 안) ·
   가로 스크롤은 의도한 상자(탭 줄·코드) 안에서만. 상태 = #v2-root.m-side / .m-aside(서랍 열림). */
.v2-mbar, .v2-scrim { display: none; }   /* 데스크톱엔 없다 — 그리드 열 순서에 안 낀다 */
@media (max-width: 900px) {
  /* 뿌리 — 100dvh: iOS 사파리 주소창이 접히고 펴져도 입력칸이 화면 밖으로 안 밀린다(100vh 는 주소창을 포함한 높이). */
  body[data-ui="v2"], body[data-ui="v2"] #app { height: 100dvh; }
  #v2-root, #v2-root.no-aside { display: flex; flex-direction: column; height: 100dvh; grid-template-columns: none; }
  #v2-root > .v2-split-x { display: none; }
  .v2-main { flex: 1; min-height: 0; }
  /* 상단 바 — [☰] [탭 줄] [타임라인]. 상태 표시줄(노치) 아래로 내려앉는다(viewport-fit=cover 일 때만 값이 있다). */
  .v2-mbar { display: flex; align-items: center; gap: 2px; flex: none; height: 46px; padding: 0 4px; padding-top: env(safe-area-inset-top, 0px);
    box-sizing: content-box; border-bottom: 1px solid var(--line); background: var(--canvas); }
  .v2-mbar-btn { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; border: 0; border-radius: 10px; background: none;
    color: var(--ink-sub); cursor: pointer; flex: none; -webkit-tap-highlight-color: transparent; }
  .v2-mbar-btn:active, .v2-mbar-btn[aria-expanded="true"] { background: var(--bg); color: var(--ink); }
  .v2-mbar-btn[hidden] { display: none; }
  .v2-mbar-ic { width: 21px; height: 21px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
  .v2-mbar-slot { flex: 1; min-width: 0; align-self: stretch; display: flex; align-items: center; }
  /* 탭 줄이 바 가운데에 산다 — 제 테두리·바탕은 벗고 가로로만 굴린다. 탭은 조금 크게(손가락). 닫기 × 는 활성 탭에만(호버가 없다). */
  .v2-mbar .v2-tabs { flex: 1; min-width: 0; height: 100%; padding: 0 2px; border: 0; background: none; }
  .v2-mbar .v2-tabs-scroll { gap: 2px; }
  .v2-mbar .v2-tab-menu { background: none; border-left: 0; }
  .v2-mbar .v2-tab { max-width: 172px; height: 100%; min-height: 34px; padding: 0 8px 0 11px; font-size: 13px; }
  .v2-mbar .v2-tab .x { width: 22px; height: 22px; }
  .v2-mbar .v2-tab-xic { width: 12px; height: 12px; }
  .v2-mbar .v2-tab-add { width: 32px; height: 32px; }
  /* 배경막 */
  .v2-scrim { display: block; position: fixed; inset: 0; z-index: 39; background: rgba(var(--shadow-ink), .42); }
  .v2-scrim[hidden] { display: none; }
  /* 서랍 — 사이드바(왼쪽)·우패널(오른쪽). 닫힘 = 화면 밖 + visibility:hidden(초점·스크린리더에서도 빠진다).
     900px 규칙이 우패널을 display:none 으로 껐던 것을 되살린다. no-aside 도 되살린다 — 홈이 no-aside 가 되면서(#1719
     바탕화면 1차) 모바일 홈 타임라인은 이 서랍으로만 열리기 때문(버튼 유무는 main.ts setAside 가 라우트별로 쥔다). */
  #v2-root.no-aside .v2-aside { display: flex; }
  .v2-side, .v2-aside { position: fixed; top: 0; bottom: 0; z-index: 40; width: min(86vw, 336px); max-width: 100vw; visibility: hidden;
    transition: transform .22s ease, visibility 0s linear .22s; overscroll-behavior: contain; }
  .v2-side { left: 0; transform: translateX(-100%); border-right: 0; padding-top: env(safe-area-inset-top, 0px); }
  /* ⚠ 위 서랍 규칙은 파일 뒤쪽의 .stu-side(같은 특정도, position: relative)에 뒤늦게 덮인다 —
     미디어쿼리는 특정도를 올리지 않으므로 '나중에 쓴 쪽'이 이긴다. position 이 relative 로 돌아가면
     사이드바가 흐름에 남아 세로를 통째로 먹고 본문(.v2-main)이 화면 밖으로 밀린다
     (실측 611px 폭: 사이드바 1128px · 본문 26px → 사실상 빈 화면. 곁칸 웹 칸이 늘 이 폭이다).
     클래스를 둘 겹쳐 되찾는다 — .stu-side 를 미디어쿼리 위로 옮기면 스튜디오 레이아웃이 깨진다. */
  .v2-side.stu-side { position: fixed; }
  .v2-aside { display: flex; right: 0; transform: translateX(100%); border-left: 0; padding-top: env(safe-area-inset-top, 0px); }
  #v2-root.m-side .v2-side, #v2-root.m-aside .v2-aside { transform: none; visibility: visible; transition: transform .22s ease, visibility 0s;
    box-shadow: 0 0 0 1px var(--line), 0 18px 48px rgba(var(--shadow-ink), .24); }
  .v2-side:focus, .v2-aside:focus { outline: none; }   /* 서랍 컨테이너의 프로그램 포커스(tabindex=-1)엔 링을 안 그린다 — 안의 첫 항목부터가 조작면이다 */
  .v2-side-foot { padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px)); }
  .v2-aside-pane { padding-bottom: env(safe-area-inset-bottom, 0px); }
  /* 서랍 안 손가락 크기 — 행 44px 안팎(iOS HIG). 글자도 본문(15px)에 맞춘다. */
  .v2-side-top { padding: 12px 12px 6px; }
  .v2-liv-btn { padding: 11px 12px; font-size: 15px; }
  .v2-side-sec { padding: 12px 14px 6px 18px; }
  .v2-find-in { height: 40px; }
  .v2-pj-row { padding: 11px 10px 11px 6px; font-size: 15px; }
  .v2-pj.open > .v2-pj-row { padding: 11px 12px 8px 8px; }
  .v2-car { width: 30px; height: 30px; font-size: 17px; }
  .v2-ss-row { min-height: 42px; padding: 8px 10px 8px calc(14px + var(--nest, 14px)); font-size: 14.5px; }
  .v2-ss-row .sub { font-size: 12.5px; }
  .v2-ss-go { opacity: 1; }                       /* 호버가 없다 — 가는 길(말풍선)은 늘 보인다 */
  .v2-ss-more, .v2-tree-more, .v2-tree-note { font-size: 14px; }
  .v2-pin .v2-ss-row { min-height: 42px; }
  .v2-apps-btn { padding: 12px 12px; font-size: 15px; }
  .v2-me { padding: 8px 4px; font-size: 14.5px; }
  .v2-flt-pop { right: 0; width: min(240px, calc(100vw - 32px)); }
  .v2-fo { padding: 9px 10px; font-size: 14px; }
  .v2-ws-menu { max-width: calc(100vw - 16px); }
  /* 우패널(타임라인) 서랍 — 머리를 상단 바 높이에 맞춘다(같은 줄로 읽힌다). */
  .v2-aside > .v2-aside-pane > .tl-wrap > .v2-aside-h, .v2-aside .v2-aside-h { min-height: 46px; padding-left: 16px; }
  .tl-card { padding: 10px 8px 10px 6px; }
  .tl-ttl { font-size: 14px; }
  .tl-sub { min-height: 32px; }
  .tl-sub-t { font-size: 13.5px; }
  .tl-scroll { padding: 10px 12px calc(22px + env(safe-area-inset-bottom, 0px)); }
  /* 가운데 화면들 — 여백을 좁히고 글자는 본문 크기 유지. */
  .v2-center { padding: 18px 16px 32px; }
  .v2-title { font-size: 21px; }
  .v2-row { padding: 12px 12px; }
  .v2-home { padding: 18px 16px 16px; }
  .v2-home-launch { padding-top: clamp(16px, 6vh, 56px); }
  .v2-home-launch .v2-h1, .v2-home-sub { font-size: 24px; }
  .v2-launch { margin-top: 18px; padding: 12px 12px 10px; border-radius: 16px; }
  .v2-launch-in { min-height: 64px; }
  .v2-launch-row { flex-wrap: wrap; }
  .v2-launch-row > .v2-launch-send { margin-left: auto; height: 38px; }
  .v2-now { margin-top: 26px; }
  .v2-now-row { padding: 10px 8px; }
  .v2-now-row .tw { flex-wrap: wrap; row-gap: 2px; }
  .v2-now-row .p { max-width: 100%; }
  .v2-livpage { padding: 8px 10px 10px; }
  .v2-frame-h { flex-wrap: wrap; row-gap: 4px; padding: 8px 12px; }
  .v2-frame-sub { display: none; }              /* '클래식 화면 · 그대로 실림' — 폰에선 제목과 [새 탭] 만 남긴다 */
  /* 런치패드 — 화면 가득, 격자는 촘촘히. */
  .v2-pad { padding: calc(12px + env(safe-area-inset-top, 0px)) 12px calc(16px + env(safe-area-inset-bottom, 0px)); }
  .v2-pad-field { height: 50px; margin-bottom: 16px; border-radius: 14px; }
  .v2-pad-grid { grid-template-columns: repeat(auto-fill, minmax(124px, 1fr)); gap: 10px; }
  .v2-pad-item { padding: 14px 10px 12px; }
  /* 프로젝트 연결 드롭다운(세션 상단바) */
  .v2-pjpick { width: min(360px, calc(100vw - 16px)); }
  .v2-pjpick-in { height: 38px; }
  .v2-pjpick-row { padding: 10px 8px; }
  /* 손잡이(경계 끌기)는 폰에 없다 */
  .v2-split { display: none; }
}
@media (max-width: 900px) and (prefers-reduced-motion: reduce) {
  .v2-side, .v2-aside, #v2-root.m-side .v2-side, #v2-root.m-aside .v2-aside { transition: none; }
}
/* 터치 화면(호버 없음) — 탭 닫기 ×·세션 행의 가는 길은 호버 없이도 보인다(태블릿 가로도 여기 든다). */
@media (hover: none) {
  .v2-tab .x { visibility: visible; }
  .v2-ss-go { opacity: 1; }
}
/* 터치 기기(폭 무관) — 입력칸 글자 16px: iOS 사파리는 16px 미만 입력칸에 포커스가 가면 화면을 확대한다(돌아오지 않는다). */
@media (pointer: coarse) {
  .v2-find-in, .v2-launch-in, input.v2-pad-search, .v2-pjpick-in, .v2-ws-in, #gate-input, #gate-email, #gate-password { font-size: 16px; }
}

/* 팝아웃 창(#1744)은 서랍 크롬(☰·타임라인 버튼)이 없다 — 좁은 화면에선 가운데 한 칸만 남긴다.
   팝아웃은 '이 세션만 큰 창으로'라는 데스크톱 손짓이고, 폰에서는 본 화면(서랍 셸)이 그 역할을 한다. */
@media (max-width: 900px) { #v2-root.solo .v2-aside { display: none; } }
/* ══ 새 셸 사이드바(레일 모드 그리드 + 프로젝트 패널) ═══════════════════════════
   ⚠ 클래스 이름의 `stu-` 는 폐기된 캔버스(실험장 studio.ts)에서 물려받은 것이다. 캔버스는 2026-08-20 에
   내렸지만(지식: canvas-view-retired-1719) **이 규칙들은 사이드바가 쓰고 있어 살아 있다** — 이름만 옛것이다. */
#v2-root.rail-mode { grid-template-columns: var(--v2-side-w) 6px minmax(0, 1fr) 6px var(--v2-aside-w); }
#v2-root.rail-mode.no-aside { grid-template-columns: var(--v2-side-w) 6px minmax(0, 1fr) 0 0; }
.stu-side { position: relative; display: flex; flex-direction: row; align-items: stretch; overflow: hidden; padding: 0; background: var(--bg); border: 0; }
.stu-panel { position: relative; width: 100%; flex: 1 1 auto; min-width: 0; min-height: 0; background: var(--gray-bg-2); border-right: 1px solid var(--line); display: flex; flex-direction: column; }
.stu-panel-h { flex: none; display: flex; align-items: center; gap: 8px; padding: 14px 14px 6px; }
.stu-panel-h b { flex: 1; font-size: 13px; }
.stu-panel-tree { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
.stu-panel-tree .v2-side { border: 0; background: transparent; width: auto; }
.stu-w-btn { min-width: 22px; height: 22px; border: 0; border-radius: 6px; background: none; color: var(--muted); font-size: 11px; font-weight: 600; cursor: pointer; padding: 0 4px; line-height: 1; font-family: inherit; }
.stu-w-btn:hover { background: var(--bg-punch); color: var(--ink); }
.ell { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.ell2 { overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
@media (prefers-reduced-motion: reduce) { .stu-peek { animation: none; } }
@media (prefers-reduced-motion: reduce) { .stu-notif { transition: none; } }
@media (prefers-reduced-motion: reduce) { .stu-desk, .stu-trash { transition: none; } }
.stu-stackpop-h .stu-w-btn { margin-left: auto; }
@media (prefers-reduced-motion: reduce) { .stu-launch, .stu-notif, .stu-ghost, .stu-w.pop { animation: none; } .stu-ghost-cur { animation: none; } }
@media (prefers-reduced-motion: reduce) { .stu-w.anim { transition: none; } .stu-scrim { transition: none; } }
/* 새 프로젝트 — 사이드바 ＋ 의 그 자리 팝오버(만들면 그 작업대로 간다) */

/* ── 탭 끌어 옮기기 + 이름 고치기(원준 2026-08-20) ── */
.v2-tab { position: relative; }
/* 잡은 탭이 이웃 위로 떠야 한다(z-index) */
/* 이웃이 미끄러지는 건 **끄는 동안만** — 평상시엔 탭이 움직일 일이 없다(transition 을 상시로 두면 첫 렌더가 흐른다). */
.v2-tabs.dnd .v2-tab { transition: transform .16s cubic-bezier(.2,.7,.3,1); }
.v2-tabs.dnd .v2-tab.dragging { transition: none; z-index: 5; cursor: grabbing;
  background: var(--bg); box-shadow: inset 0 2px 0 var(--blue), 0 6px 16px rgba(16, 24, 40, .16); }
.v2-tab-in { width: 150px; max-width: 46vw; min-width: 90px; height: 20px; border: 1px solid var(--blue); border-radius: 5px;
  padding: 0 5px; font: inherit; font-size: 12.5px; background: var(--bg); color: var(--ink); }
.v2-tab-in:focus { outline: none; box-shadow: 0 0 0 3px rgba(45, 107, 240, .12); }

/* [모든 탭] — 줄 오른쪽 끝에 붙어 있는 목록 단추(줄이 굴러가도 늘 보이게 sticky). */
.v2-tab-menu { display: inline-flex; align-items: center; gap: 3px; height: 36px; padding: 0 9px; border: 0; border-left: 1px solid var(--line); background: var(--gray-bg-2); font: inherit; font-size: 11.5px; color: var(--muted-head); cursor: pointer; flex: none; }
.v2-tab-menu:hover { color: var(--blue); }
.v2-tab-menu .n { font-variant-numeric: tabular-nums; font-weight: 600; }
/* [모든 탭] 목록 — anchoredPopover 의 .dash-pop 은 **자리만** 잡는다(20-dashboard.css). 배경·테두리·그림자는
   여는 쪽이 준다. 안 주면 떠 있는 글자가 뒤 화면에 그대로 겹쳐 읽히지 않는다(상민님 2026-08-20 신고). */
.v2-tabpop { width: 320px; max-width: 86vw; padding: 8px; background: var(--bg); border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 12px 32px rgba(16, 32, 64, .16), 0 2px 6px rgba(16, 32, 64, .08); }
.v2-tabpop-h { margin: 2px 4px 6px; font-size: 11.5px; color: var(--muted); }
.v2-tabpop-find { width: 100%; height: 28px; margin-bottom: 6px; padding: 0 9px; border: 1px solid var(--line-net); border-radius: 8px; font: inherit; font-size: 12.5px; background: var(--bg); color: var(--ink); }
.v2-tabpop-find:focus { outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px rgba(45,107,240,.10); }
.v2-tabpop-list { max-height: 52vh; overflow: auto; display: flex; flex-direction: column; gap: 1px; }
.v2-tabpop-row { display: flex; align-items: center; gap: 2px; border-radius: 8px; }
.v2-tabpop-row:hover { background: var(--bg-tint); }
.v2-tabpop-row.on { background: var(--bg-tint-2); }
.v2-tabpop-row .go { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; padding: 7px 8px; border: 0; background: none; font: inherit; font-size: 12.5px; color: var(--ink); text-align: left; cursor: pointer; }
.v2-tabpop-row .go .n { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-tabpop-row.on .go { font-weight: 700; }
.v2-tabpop-row .x { flex: none; width: 24px; height: 24px; margin-right: 4px; border: 0; background: none; border-radius: 6px; color: var(--muted-2); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; }
.v2-tabpop-row .x:hover { background: var(--bg-punch); color: var(--ink); }

/* ── 테마 3단 토글(#1683) — 사이드바 하단 세그먼트(시스템/라이트/다크). web/v2/side.ts themeSeg(). ── */
/* 테마 3단(#1683) — 지금 사는 곳은 [내 프로필 · 환경설정] ▸ 화면(#1843). 사이드바 발치에서 옮겨 왔다. */
.v2-theme { display: flex; gap: 2px; padding: 2px; border: 1px solid var(--line); border-radius: 9px; background: var(--bg-tint); }
.v2-theme-opt { flex: 1; border: 0; background: transparent; font: inherit; font-size: 12px; font-weight: 600; color: var(--muted); padding: 4px 0; border-radius: 7px; cursor: pointer; transition: color 120ms ease, background 120ms ease; }
.v2-theme-opt:hover { color: var(--ink-sub); }
.v2-theme-opt.on { background: var(--surface); color: var(--ink); box-shadow: 0 1px 2px rgba(var(--shadow-ink), .10); }
/* 'AI 세션도 이 테마로'(#1683 후속) — 세그먼트 바로 아래 한 줄. 화면 테마와 한 묶음으로 읽히게 붙여 둔다. */
.v2-theme-ai { display: flex; align-items: center; gap: 6px; margin: 5px 10px 0; font-size: 11.5px; color: var(--muted); cursor: pointer; user-select: none; }
.v2-theme-ai:hover { color: var(--ink-sub); }
.v2-theme-ai-cb { margin: 0; width: 13px; height: 13px; accent-color: var(--blue-fill); cursor: pointer; }

/* 기록 완전 삭제(#1850) — 보관(×)과 같은 자리·같은 크기지만 뜻이 정반대라 평소에도 살짝 붉다.
   보관은 되돌릴 수 있고 이건 못 되돌린다 — 색이 그 차이를 먼저 말한다. */
.v2-ss-del { color: var(--danger); opacity: .38; }
.v2-ss-row:hover .v2-ss-del { opacity: .85; }
.v2-ss-del:hover { opacity: 1; }

/* 완전 삭제 확인창의 범위 선택(#1850 P2) — '무엇을 지울지'를 개수만이 아니라 이름까지 보여준다.
   개수만 보이면 사람은 무엇이 사라지는지 모른 채 체크한다. */
.sess-purge { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }
.sess-purge-h { display: flex; flex-direction: column; gap: 1px; font-size: 13px; font-weight: 600; color: var(--ink); margin: 2px 0 0; }
.sess-purge-h .sub { font-size: 12px; font-weight: 500; color: var(--muted); }
.sess-purge-row { display: flex; gap: 8px; align-items: flex-start; cursor: pointer; padding: 6px 8px; border-radius: 8px; background: var(--bg-tint-2, #F4F6FA); }
.sess-purge-row:hover { background: var(--bg-tint, #F6FAFF); }
.sess-purge-row input { margin-top: 2px; flex: none; }
.sess-purge-row .b { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sess-purge-row .n { font-size: 13px; font-weight: 600; }
.sess-purge-row .h { font-size: 12px; color: var(--blue); }
.sess-purge-row .l { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 남는 것(규칙 B — 그 뒤에 남이 손댄 것)·'결과물은 남기기' 한 줄 — 체크행과 같은 결이되 고를 수 없음이 보이게 배경 없이. */
.sess-purge-keep { display: flex; flex-direction: column; gap: 1px; margin: 0; padding: 4px 8px; font-size: 12.5px; }
.sess-purge-keep .n { color: var(--ink); }
.sess-purge-keep .w { font-size: 12px; color: var(--muted); }
.sess-purge-only { align-self: flex-start; font-size: 12px; color: var(--ink-note); padding: 2px 8px; }
/* 휴지통 여러 개 선택 — 행 앞 체크박스 + 고른 것이 있을 때만 뜨는 동작 줄 */
.v2-bin-row .sel { margin: 0 2px 0 0; flex: none; }
.v2-bin-selbar { display: flex; align-items: center; gap: 10px; padding: 6px 8px 8px; margin: 0 0 4px; border-bottom: 1px solid var(--line); font-size: 12.5px; }
.v2-bin-selbar[hidden] { display: none; }
.v2-bin-selbar .n { color: var(--ink-note); font-weight: 600; margin-right: 4px; }
.v2-bin-selbar .btn-text.danger { color: var(--danger); }

/* ── 아카이브 · 휴지통(#1851) — 사이드바 발치의 두 행 + 가운데 화면. web/v2/side.ts binRows() · web/v2/bins.ts ── */
/* 두 행은 프로젝트 행과 같은 기둥(아이콘 16 → 글자)·같은 높이를 쓰되 **보통 글씨·흐린 아이콘** — 폴더(내용)가 아니라
   '치워 둔 곳'이라 목록보다 먼저 읽히면 안 된다. 트리 맨 아래(기본)에서는 위와 구분선으로 띄우고, 발치에 고정하면
   트리 밖(스크롤 무관)에 같은 모양으로 선다. */
.v2-bins { margin-top: 14px; padding-top: 8px; border-top: 1px solid var(--line); }
.v2-bins-fixed { margin: 0; padding: 6px var(--side-x, 8px) 6px; border-top: 1px solid var(--line); flex: none; }
.v2-bin { display: flex; align-items: center; gap: 4px; padding: 7px 10px 7px 8px; min-height: var(--row-h, 34px); border-radius: 8px; font-size: 13.5px; font-weight: 600; line-height: 1.4; color: var(--ink-sub); text-decoration: none; }
.v2-bin + .v2-bin { margin-top: 2px; }
.v2-bin:hover { background: var(--bg); color: var(--ink); }
.v2-bin.on { background: var(--bg); color: var(--ink); box-shadow: inset 0 0 0 1px var(--line-net); }
.v2-bin-ic { width: 16px; height: 16px; flex: none; margin-left: 20px; fill: none; stroke: var(--muted-2); stroke-width: 1.8; stroke-linejoin: round; stroke-linecap: round; }
.v2-bins-fixed .v2-bin-ic { margin-left: 4px; }
.v2-bin:hover .v2-bin-ic, .v2-bin.on .v2-bin-ic { stroke: var(--blue); }
.v2-bin .n { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-left: 4px; }
/* 아래 고정 압정 — 프로젝트 행의 압정과 같은 규약(자리는 늘 차지, 손을 얹으면 보임, 켜져 있으면 늘 보임). */
.v2-bin:hover .v2-bin-pin, .v2-bin-pin:focus-visible { opacity: 1; }
/* 지난 세션 행의 휴지통 단추 — 보관(×)과 같은 자리·같은 크기, 손을 얹으면 위험색. */
.v2-ss-trash .v2-ss-x-ic { width: 13px; height: 13px; stroke-width: 1.8; stroke-linejoin: round; }

/* 가운데 화면 — 홈·확인할 것(v2-now-row)과 같은 행 문법. 아카이브는 프로젝트 카드(머리 + 세션 목록), 휴지통은 묶음 둘. */
.v2-bin-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.v2-bin-top > div { min-width: 0; }
.v2-bin-emptyb { flex: none; margin-top: 14px; }
.v2-bin-sec { margin-top: 26px; }
.v2-bin-cards { margin-top: 22px; display: flex; flex-direction: column; gap: 14px; }
.v2-bin-card { border: 1px solid var(--line-net); border-radius: 12px; background: var(--bg); overflow: hidden; }
.v2-bin-head { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--line); }
.v2-bin-head .tw { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.v2-bin-head .t { font-size: 14.5px; font-weight: 750; color: var(--ink); text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-bin-head .t:hover { text-decoration: underline; }
.v2-bin-head .p { font-size: 12px; color: var(--muted); }
.v2-bin-fold { width: 18px; height: 18px; flex: none; fill: none; stroke: var(--muted-2); stroke-width: 1.8; stroke-linejoin: round; }
.v2-bin-fold.sm { width: 15px; height: 15px; margin: 0 3px 0 1px; }
.v2-bin-list { padding: 6px; }
.v2-bin-card .v2-bin-list { padding: 6px 8px; }
.v2-bin-row { display: flex; align-items: center; gap: 10px; padding: 7px 8px; border-radius: 9px; color: inherit; }
.v2-bin-row:hover { background: var(--bg-tint); }
.v2-bin-row .tw { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: 8px; text-decoration: none; color: inherit; }
.v2-bin-row .t { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13.5px; font-weight: 600; color: var(--ink); }
.v2-bin-row.past .t { font-weight: 500; }
.v2-bin-row a.tw:hover .t { text-decoration: underline; }
.v2-bin-row .p { font-size: 11.5px; color: var(--muted-2); flex: none; max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-bin-row .st { font-size: 12px; color: var(--muted); flex: none; font-variant-numeric: tabular-nums; }
.v2-bin-row .btn-text { flex: none; }
.v2-bin-row .btn-text.danger { color: var(--danger); }
.v2-bin-more { margin: 4px 8px 2px; }
.v2-bin-empty { margin: 6px 8px; font-size: 12.5px; color: var(--muted); }
.v2-bin-fine { margin-top: 28px; font-size: 12.5px; color: var(--muted); display: flex; align-items: center; gap: 8px; }
@media (max-width: 900px) {
  .v2-bin-row { flex-wrap: wrap; }
  .v2-bin-row .p { max-width: 100%; }
}


/* ── [외부 앱 연결] 관리자 구역(#1719) — 같은 화면의 '조직' 층. 개인 층과 **눈에 띄게 다른 바탕**을 준다:
      여기서 누르는 것은 나 하나가 아니라 팀 전체에 걸리는 결정이라, 착각으로 누르면 안 된다. ── */
.cn-adm { border: 1px solid var(--line); border-radius: 12px; padding: 14px 16px; background: var(--bg-tint); }
.cn-adm .cn-sec-h { display: flex; align-items: center; gap: 8px; justify-content: space-between; }
.cn-adm-badge { font-size: 11.5px; font-weight: 700; color: var(--muted-2);
  border: 1px solid var(--line); border-radius: 999px; padding: 2px 8px; white-space: nowrap; }
.cn-muted { color: var(--muted-2); }
.cn-guide { margin: 10px 0 12px; display: flex; flex-direction: column; gap: 8px; }
.cn-steps { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 5px;
  font-size: 13px; line-height: 1.6; color: var(--ink-sub); }
.cn-steps code, .cn-copy-v { font-size: 11.5px; word-break: break-all; }
/* 콘솔에 그대로 붙여넣는 값들(콜백 주소·허용범위) — 읽으라고 두는 게 아니라 **복사하라고** 두는 자리다. */
.cn-copy { display: grid; grid-template-columns: 1fr auto; gap: 2px 10px; align-items: center;
  background: var(--bg-sub); border-radius: 8px; padding: 8px 10px; }
.cn-copy-k { grid-column: 1 / -1; font-size: 11.5px; font-weight: 700; color: var(--muted-2); }
.cn-copy-v { white-space: pre-wrap; }
.cn-fields { display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px; }
.cn-f { display: flex; flex-direction: column; gap: 4px; }
.cn-f-k { font-size: 11.5px; font-weight: 700; color: var(--muted-2); }
.cn-in { width: 100%; padding: 8px 10px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--bg); color: var(--ink); font-size: 13px; }
.cn-in:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.cn-sum-adm b { color: var(--ink-sub); }

/* 접히는 안내 — 늘 보여야 하는 건 '콘솔에 넣을 값'이고, 읽는 절차는 처음 한 번만 필요하다. */
.cn-steps-wrap { border: 1px solid var(--line); border-radius: 8px; padding: 0 10px; background: var(--bg); }
.cn-steps-wrap[open] { padding-bottom: 10px; }
.cn-steps-sum { cursor: pointer; padding: 9px 0; font-size: 12.5px; font-weight: 700; color: var(--ink-sub); }
.cn-steps-sum::marker { color: var(--muted-2); }
.cn-steps-wrap .cn-help { margin: 2px 0 8px; }

/* ── 「정리」 모드(#1719 안 C, 원준 2026-08-24) ────────────────────────────────
   머리줄에서 「필터」 글자를 뺀 자리에 [정리]가 들어왔다. 실측: 글자 있는 필터 버튼 60px,
   아이콘 버튼 27px — 글자 하나를 내주면 넷이 되고도 머리줄이 6px 좁아진다(114 → 108). */
.v2-side-sec .v2-flt-btn { padding: 0; width: 27px; justify-content: center; }
.v2-side-sec .v2-flt-btn.has { padding: 0 6px; width: auto; }   /* 배지가 붙으면 그만큼만 늘어난다 */
/* 켜진 개수 배지 — 글자를 뺀 대신 '지금 걸러져 있다'를 이게 말한다. */
.v2-flt-n { min-width: 15px; height: 15px; padding: 0 4px; border-radius: 99px; background: var(--blue); color: #fff;
  font-size: 10px; font-weight: 700; line-height: 15px; text-align: center; font-variant-numeric: tabular-nums; }
.v2-tidyb.on { color: #fff; background: var(--blue); border-color: var(--blue); }
.v2-tidyb.on:hover { background: var(--blue-deep, var(--blue)); }

/* 고르는 줄 — 체크칸이 캐럿 앞에 선다. 켜져 있는 동안엔 hover 단추(＋·핀)를 감춘다:
   고르는 중에 눌러 세션이 열리면 그게 곧 모드에서 튕겨 나가는 사고다. */
.v2-ck { flex: none; width: 15px; height: 15px; margin-right: 1px; border: 1.6px solid var(--muted-2);
  border-radius: 4px; display: grid; place-items: center; background: var(--bg); }
.v2-ck-ic { width: 10px; height: 10px; fill: none; stroke: #fff; stroke-width: 2.8; stroke-linecap: round; stroke-linejoin: round; opacity: 0; }
.v2-pj-row.sel .v2-ck { background: var(--blue); border-color: var(--blue); }
.v2-pj-row.sel .v2-ck-ic { opacity: 1; }
.v2-pj-row.sel { background: var(--bg-tint-2); }
.v2-pj-row.v2-pick .v2-pinb, .v2-pj-row.v2-pick .v2-newb { display: none; }

/* 발치 막대 — 고른 개수와 할 일이 늘 보인다. 모드에 갇힌 느낌을 없애는 건 [끝내기]가 늘 곁에 있는 것이다. */
.v2-tidybar { display: flex; align-items: center; gap: 10px; padding: 9px 12px 9px 16px;
  border-top: 1px solid var(--line); background: var(--bg-tint); }
.v2-tidybar-k { flex: 1; min-width: 0; font-size: 12px; font-weight: 700; color: var(--ink-sub);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
